title: Adding stimulus and importmaps to an existing Rails 6.1 app
body: <p>I've got a Rails 6.1 app which has been upgraded from Rails 4 -&gt; 5 -&gt; 6, so it's mature.</p>
  <p>It still uses asset pipeline and with the future of Rails 7.0 I'm going to keep it that way. I wanted to start using <a href="https://github.com/hotwired/stimulus-rails" rel="nofollow noreferrer">stimulus</a> + <a href="https://github.com/rails/importmap-rails" rel="nofollow noreferrer">importmaps</a>, so I've followed along with the install.</p>
  <p>After installing importmaps and stimulus through hotwire I'm getting the following errors in Firefox 91 when loading my app;</p>
  <pre><code>Uncaught SyntaxError: import declarations may only appear at top level of a module
  Uncaught TypeError: Error resolving module specifier “application”. Relative module specifiers must start with “./”, “../” or “/”.
  </code></pre>
  <p>My importmap.rb</p>
  <pre><code>Rails.application.config.importmap.draw do
    pin &quot;@hotwired/stimulus&quot;, to: &quot;stimulus.js&quot;
    pin &quot;@hotwired/stimulus-importmap-autoloader&quot;, to: &quot;stimulus-importmap-autoloader.js&quot;
    pin_all_from &quot;app/javascript/controllers&quot;, under: &quot;controllers&quot;
  
    pin &quot;application&quot;
  
    # Use libraries available via the asset pipeline (locally or via gems). # Rails 7.0 required
    # pin &quot;@rails/actioncable&quot;, to: &quot;actioncable.esm.js&quot;     
    # pin &quot;@rails/activestorage&quot;, to: &quot;activestorage.esm.js&quot; 
  
    # Use libraries directly from JavaScript CDNs (see https://www.skypack.dev, https://esm.sh, https://www.jsdelivr.com/esm)
    # pin &quot;vue&quot;, to: &quot;https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js&quot;
    # pin &quot;d3&quot;, to: &quot;https://esm.sh/d3?bundle&quot;
  
    # Pin vendored modules by first adding the following to app/assets/config/manifest.js:
    # //= link_tree ../../../vendor/assets/javascripts .js
    # pin_all_from &quot;vendor/assets/javascripts&quot;
  end
  </code></pre>
  <p>I've kept all my javascript in app/assets/javascripts directory which should still be handled by the asset pipeline.</p>
  <p>I've got the following app/assets/javascripts/importmap.json.erb</p>
  <pre><code>{
    &quot;imports&quot;: { 
      &quot;turbo&quot;: &quot;&lt;%= asset_path &quot;turbo&quot; %&gt;&quot;,
      &lt;%= importmap_list_with_stimulus_from &quot;app/assets/javascripts/controllers&quot;, &quot;app/assets/javascripts/libraries&quot; %&gt;
    }
  }
  </code></pre>
  <p>application.js is;</p>
  <pre><code>// This is the main application.js, there can only be one.
  //
  // Configure your import map in config/importmap.rb
  
  // import &quot;@rails/actioncable&quot;   // Rails 7.0 required
  // import &quot;@rails/activestorage&quot; // Rails 7.0 required
  
  import &quot;@hotwired/stimulus-importmap-autoloader&quot;
  </code></pre>
  <p>I also have the following line in my application.html.erb</p>
  <pre><code>&lt;%= stylesheet_link_tag    &quot;application&quot; %&gt;
  &lt;%= javascript_include_tag &quot;application&quot; %&gt;
  &lt;%= csrf_meta_tags %&gt;
  &lt;%= javascript_include_tag &quot;turbo&quot;, type: &quot;module-shim&quot; %&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  &lt;%= yield :head %&gt;
  &lt;%= javascript_importmap_tags %&gt;
  </code></pre>
  <p>manifest.js is;</p>
  <pre><code>//= link_tree ../images
  //= link_directory ../javascripts .js
  //= link_directory ../stylesheets .css
  //= link_tree ../javascripts
  </code></pre>
  <p><strong>Edit</strong></p>
  <p>Checking the Elements tab in Chrome and I've already loaded es-module-shims but in Firefox I still get the errors;</p>
  <pre><code>Uncaught SyntaxError: import declarations may only appear at top level of a module
  Uncaught TypeError: Error resolving module specifier “application”. Relative module specifiers must start with “./”, “../” or “/”.
  </code></pre>
  <p>Here is the code which loads the es-module-shim</p>
  <pre><code>&lt;script src=&quot;/assets/es-module-shims-e320a414bc4656be79c9c722c91afd9bc40140edf48616fbf72fb2da3c1fdcaa.js&quot; async=&quot;async&quot; data-turbo-track=&quot;reload&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;module&quot;&gt;import &quot;application&quot;&lt;/script&gt;
  </code></pre>
  <p><strong>Edit</strong></p>
  <p>The following error can be safely ignored;</p>
  <pre><code>Uncaught TypeError: Error resolving module specifier “application”. Relative module specifiers must start with “./”, “../” or “/”.
  </code></pre>
  <p>Ref: <a href="https://github.com/rails/importmap-rails#expected-errors-from-using-the-es-module-shim" rel="nofollow noreferrer">https://github.com/rails/importmap-rails#expected-errors-from-using-the-es-module-shim</a></p>
  <p><strong>Edit</strong></p>
  <p>The other error disappeared when I changed my application.html.erb head to the following</p>
  <pre><code>&lt;%= csrf_meta_tags %&gt;
  &lt;%= csp_meta_tag %&gt;
  
  &lt;%= stylesheet_link_tag    &quot;application&quot; %&gt;
  &lt;%= javascript_importmap_tags %&gt;
  
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  &lt;%= yield :head %&gt;
  </code></pre>