webpacker: Refused to execute script from because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

Hello, I’m having a problem with deploying on aws elasticbeanstalk. On localhost it runs normally but when deploy to eb I got this error.

  • on chrome screen shot 2561-08-12 at 11 16 49

  • on safari screen shot 2561-08-12 at 17 44 56

I have been trying to figured it out for days but no luck.

I’m using:

- Rails 5.2.1
- gem 'webpacker', '~> 3.5'
- yarn 1.9.4

Here is my files structures. screen shot 2561-08-13 at 21 45 12

Here is my application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>IcOpenhouse</title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <link href="https://fonts.googleapis.com/css?family=Kanit:300&amp;subset=thai" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Megrim" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Mitr:200&amp;subset=thai" rel="stylesheet">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">

    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all'%>
    <%= stylesheet_pack_tag 'bootstrap'%>
    <%= javascript_pack_tag 'index' %>

  </head>

  <body>
    <%= yield %>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </body>
</html>

My package.json

{
  "name": "ic-openhouse",
  "private": true,
  "scripts": {
    "postinstall": "npm rebuild node-sass"
  },
  "dependencies": {
    "@babel/runtime": "^7.0.0-beta.56",
    "@fortawesome/fontawesome-free": "^5.2.0",
    "@rails/webpacker": "3.5",
    "axios": "^0.18.0",
    "babel-preset-react": "^6.24.1",
    "bootstrap": "^4.1.3",
    "gsap": "^2.0.1",
    "jquery": "^3.3.1",
    "moveto": "^1.7.3",
    "popper.js": "^1.14.4",
    "prop-types": "^15.6.2",
    "query-string": "^6.1.0",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-router-dom": "^4.3.1",
    "react-scroll-parallax": "^1.3.5",
    "resolve-url-loader": "^2.3.0",
    "scrollmagic": "^2.0.5"
  },
  "devDependencies": {
    "babel-eslint": "^8.2.6",
    "eslint": "^5.2.0",
    "eslint-config-react-app": "^2.1.0",
    "eslint-plugin-flowtype": "^2.50.0",
    "eslint-plugin-import": "^2.13.0",
    "eslint-plugin-jsx-a11y": "^6.1.1",
    "eslint-plugin-react": "^7.10.0",
    "prettier": "^1.14.0",
    "webpack-dev-server": "^2.11.1"
  }
}

config/webpack/environment.js

const { environment } = require('@rails/webpacker')
const customConfig = require('./custom')

const webpack = require('webpack')
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery',
  Popper: ['popper.js', 'default']
}))

// Take the assets stored in node_modules packages
const sassLoader      = environment.loaders.get('sass');
const findSassLoader  = loader => (loader === 'sass-loader' || loader.loader === 'sass-loader');
const sassLoaderIndex = sassLoader.use.findIndex(findSassLoader);

sassLoader.use.splice(sassLoaderIndex, 0, {
  loader: 'resolve-url-loader',
});

// Merge custom config
environment.config.merge(customConfig)

module.exports = environment

config/webpacker.yml

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_output_path: packs
  cache_path: tmp/cache/webpacker

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  resolved_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  extensions:
    - .jsx
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg
    - .ttf

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: /node_modules/


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Cache manifest.json for performance
  cache_manifest: true

I don’t know whether the problem is from webpacker config or the aws nginx server. Please ask me, if you need more information.

  • I have tried adding MIME type to config/initializers/mime_types.rb according to the rails repo
  • I have tried adding .ebextension/nginx.config according to this file
  • I have tried upgrading webpacker according to issue 1427

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 17
  • Comments: 24 (8 by maintainers)

Commits related to this issue

Most upvoted comments

I had same issue. In my case, I had set config/routes.rb like below to use vue router

root to: 'application#index'
get "/*path", to: "application#index", format: false

Because of this, when I trying to get static file like application-***.js it redirects to application#index and that mime “text/html” error occurs.

So I checked config/environments/production.rb and after I set ENV[‘RAILS_SERVE_STATIC_FILES’], it worked.

so if you’re trying to run server in production env and not using nginx to serve static file, setting RAILS_SERVE_STATIC_FILES might solve the problem.

config/environments/production.rb
  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?

I followed this description since I don’t have external services, I created an environment variable RAILS_SERVE_STATIC_FILES=1 I used Heroku with docker and it helped me.

@jakeNiemiec See the following:

If we had access to webpack 4 at the time (wasn’t stable on webpacker yet), we could have used [name]-[contenthash].js instead…

So…

Webpacker does use content hash: #2094

…it does now 😄, but even then only with 4.x; [contenthash] isn’t available in webpack pre-4. This has been an issue for a while before webpacker 4.x was stable (and before that PR was merged), and still isn’t available in 3.x AFAIK.

Splitting the chunks wouldn’t have worked either, since they still rely on nondeterministic hashing, unfortunately, so running the compilation step on multiple machines simultaneously would not be guaranteed to result in different hashes for the same chunk content anyway.

It’s all moot (or should be) now that you can use 4.x, but sadly we’re stuck on 3.x for various reasons at the moment, so it’ll have to do.

@kjleitz I was facing exactly the same problem. Cloudfront is redirecting to the server as the file is not synced with cloudfront. Rails only upload the files in the assets directory. By changing the output path, I got it working.

Update webpacker.yml file with:

public_output_path: assets/packs

Re-run the webpacker install command:

bundle exec rails webpacker:install

Select ’n’ for all it prompts to not overwrite your existing files.

Read more on Getting CloudFront to work with Webpacker Rails 5

I’ve had the same issue, which only seems to arise when it’s deployed to a production (or production-like) environment, when using a CDN. Sometimes I can refresh a few times and finally get a successful response, but then subsequent refreshes have the same issue and it takes a bunch to get it to load. It doesn’t happen with our other compiled assets (from the traditional pipeline in public/assets/, etc.), only with stuff in public/packs/. Doesn’t happen every deployment, either; once every couple deployments it “just works”.

There may be a separate CDN issue at play for us, but I’m not sure. We use Fastly, and when I check the cache servers for a “flickering” URL it seems that only a fraction of them are returning 200s, and the others are returning 301s to a non-existent resource. Again, though, doesn’t happen with the material from the regular asset pipeline.

I wonder if there’s some kind of invalid initial response (or timeout) that can happen when the first request is made for the Webpacker-packed resource (a symptom of which might be that a Content-Type of “text/html” is returned instead of “application/javascript”), and the CDN is caching that invalid response?

I’m not very familiar with exactly how CDNs function, but it seems like a hint.

@pawneetdev I did get this working, but it was actually a bigger issue than I realized:

We use Ansible for deployments, which runs assets:precompile on each of our [multiple] appservers, independently, as part of the process. The appservers are behind a load balancer which round-robins requests. Webpack/Webpacker was appending a different (timestamp-based) hash to each of the asset files on each server, meaning there would be different bundled filenames for each respective public/packs directory on the appservers. The CDN was picking up/caching only one of them, so only a fraction of the time (when the same appserver that rendered the script tag onto the page was the one the CDN picked up the script from) it would succeed, and the rest of the time it would fail to fetch the file.

I fixed this by modifying the webpack config to use the last commit SHA as the hash, as opposed to the default timestamp-based hash, ensuring that they would be identical across the appservers. Unfortunately, this blows away any ability to retain a cache across deploys… but it’s better than the script not loading at all 😅

If we had access to webpack 4 at the time (wasn’t stable on webpacker yet), we could have used [name]-[contenthash].js instead, because IIRC contenthash hashes the file contents rather than using the timestamp of compilation. You can try that if you run into similar issues.

@FFEVER did you ever figure this out?

@pawneetdev A bit late to the party BUT: Your solution really works for me. However I still can’t figure out why /packs is not available just like /assets/. Maybe there’s a configuration option we could use instead…?

In my case I deploy with capistrano. NGINX serves everything under /public and I’ve double-checked that every asset is in there. So does anybody know why cloudfront doesn’t pick up anything under /packs?

This started happened to me during a switch from passenger to puma.

I think related to https://github.com/rails/webpacker/issues/1784 among other issues

Theoretically RAILS_SERVE_STATIC_FILES should work, but I’m pretty sure this is defaulted to true on my version of rails ( >~4.2), which makes me blindly point my finger at puma.

I’m switching the nginx config to include.

    location ^~ /packs/ {
        gzip_static on;
        expires max;
      }

Which should hopefully let nginx serve the the assets, rather than the theoretical handoff that happens between puma / rails RAILS_SERVE_STATIC_FILES.

(Still looking into this, as this did not seem to work for me)


Setting env variable RAILS_SERVE_STATIC_FILES = false

Then

location / {
        location ^~ /assets/ {
          gzip_static on;
          gzip on;
          expires max;
          root /var/app/current/public;
        }

        location ^~ /packs/ {
          gzip_static on;
          gzip on;
          expires max;
          root /var/app/current/packs;
        }
      }

Seemed to work for me.

I’m sorry for didn’t reply to this. I have never found the solution yet. Fortunately, it is only a small project that serves only a static website, so I decided to move the whole project to pure React. Feel free to share any other solutions.