javascriptruby-on-railsruby-on-rails-7import-maps

JS file is blocked due to bad MIME in production


In my Rails 7 project I have been using importmap for importing JS modules. here is the config:

# config/importmap

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "app/javascript/lib", under: "lib"
pin "@yaireo/tagify", to: "@yaireo--tagify.js" # @4.26.5
pin "@simonwep/pickr", to: "@simonwep--pickr.js" # @1.9.1

JS directory looks like this (app/javascript):

├── javascript
│   ├── application.js
│   ├── controllers
│   │   ├── file1.js
│   │   └── file2.js
│   └── lib
│       ├── file3.js
│       └── file4.js

in asset.rb I've also included these:

Rails.application.config.assets.precompile += %w( lib/file3.js )
Rails.application.config.assets.precompile += %w( lib/file4.js )
Rails.application.config.assets.precompile += %w( controllers/file1.js )
Rails.application.config.assets.precompile += %w( controllers/file2.js )

And app/javascript/application.js looks like this (maybe here is the problem):

import { Turbo } from "@hotwired/turbo-rails"
Turbo.start();

import { Application } from '@hotwired/stimulus';
import File1Controller from './controllers/file1.js'
import File2Controller from './controllers/file2.js'


const application = Application.start();
application.register('file1', File1Controller);
application.register('file2', File2Controller);

And lastly app/assets/config/mainfest.js looks like this:

//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js
//= link_tree ../builds

All working great in development on localhost but it production it's showing:

Loading module from “https://mysweet.domain/assets/controllers/file1.js” was blocked because of a disallowed MIME type (“text/html”).

How could I resolve it?


Solution

  • ... blocked because of a disallowed MIME type (“text/html”)

    Because you're getting a 404 for this file.

    Do not use relative imports './controllers/file1.js', this only works in development. Relative path does not match anything in your import-map, that means the request comes in for undigested /assets/controllers/file1.js this only works in development because sprockets is serving the assets and it can handle both digested and undigested urls. In production you have precompiled assets that can be fetched with a digested url only.

    You have to use imports that will match your import-map:

    $ bin/importmap json
    {
      "imports": {
        ...
        "controllers/file1": "/assets/controllers/file1-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
        "controllers/file2": "/assets/controllers/file2-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
        "lib/file3":         "/assets/lib/file3-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
        "lib/file4":         "/assets/lib/file4-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
      }
    }
    
    import File1Controller from 'controllers/file1'
    import File2Controller from 'controllers/file2'
    import File3Lib from 'lib/file3'
    import File4Lib from 'lib/file4'