Search code examples
ruby-on-railsstimulusjshotwire-railsimport-mapsuppy

Loading uppy with Rails 7 and stimulus and importmaps


Is it doable to load Uppy into a vanilla Rails app via the Rails 7 importmaps?

If you end up pinning @uppy/core, you get a lot of dependencies added to your importmap file:

bin/importmap pin @uppy/core

...but when you try to access it via a Stimulus controller like:

import Uppy from '@uppy/core';

You get a variety of not-so-helpful errors.

Safari shows:

syntaxerror: Importing binding name 'default' cannot be resolved by star export entries.

And Chrome has a few different responses:

SyntaxError: The requested module 'classnames' does not provide an export named 'default'

(I've also seen this be a problem for mime-match instead of classnames.

I'm a bit over my head in terms of debugging this- it's tricky to see where the issue might stem from. Is this a "can't really use the Rails 7 importmaps" type of answer?


Solution

  • I think this has to do with different import styles supported in different envs. The maintainers at jspm and importmap-rails have been encouraging users to file issues or fixes with dependencies. e.g.

    I was able to reproduce the Failed to register controller: uppy (controllers/uppy_controller) SyntaxError: The requested module 'mime-match' does not provide an export named 'default' issue you saw when using unpkg.

    JSPM doesn't seem to have the issue and I think does a bit more to smooth these out. You may want to try switching by using the --from jspm flag. Though, I believe that's the default.

    ❯ ./bin/importmap pin @uppy/core @uppy/drag-drop --from jspm
    
    

    That was enough for me to get a basic controller to load Uppy and its drag-drop plugin:

    import { Controller } from "@hotwired/stimulus"
    import { Uppy } from "@uppy/core"
    import { default as DragDrop }  from "@uppy/drag-drop"
    
    // Connects to data-controller="uppy"
    export default class extends Controller {
      connect() {
        const uppy = new Uppy({ })
          .use(DragDrop, {
            target: "#drag-drop"
          })
        window.uppy = uppy;
    

    I didn't experiment further. There may be more needed.