Webpacker: Deployment to heroku results in no assets

Created on 9 Jun 2017  路  16Comments  路  Source: rails/webpacker

Hi,

I'm trying to deploy to a heroku review app cloned by our staging environment. I've created a config/webpack/staging.js which is the exact copy of config/webpack/production.js which I haven't modified:

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

/* eslint global-require: 0 */

const webpack = require('webpack')
const merge = require('webpack-merge')
const CompressionPlugin = require('compression-webpack-plugin')
const sharedConfig = require('./shared.js')

module.exports = merge(sharedConfig, {
  output: { filename: '[name]-[chunkhash].js' },
  devtool: 'source-map',
  stats: 'normal',

  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      minimize: true,
      sourceMap: true,

      compress: {
        warnings: false
      },

      output: {
        comments: false
      }
    }),

    new CompressionPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
    })
  ]
})

I've also added a staging environment to config/webpacker.yml:

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

default: &default
  source_path: frontend
  source_entry_path: packs
  public_output_path: packs

  extensions:
    - .coffee
    - .erb
    - .js
    - .jsx
    - .ts
    - .vue
    - .sass
    - .scss
    - .css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default

  dev_server:
    host: 0.0.0.0
    port: 8080
    https: false

test:
  <<: *default

  public_output_path: packs-test

staging:
  <<: *default

production:
  <<: *default

The build log of the review app shows that node and yarn were picked up and installed by Heroku (though they are older versions than the one of I use locally):

-----> Installing node-v6.10.0-linux-x64
-----> Installing yarn-0.22.0
...
       yarn install v0.22.0
       warning No license field
       [1/4] Resolving packages...
       [2/4] Fetching packages...
       warning [email protected]: The platform "linux" is incompatible with this module.
       info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
       [3/4] Linking dependencies...
       [4/4] Building fresh packages...
       Done in 58.36s.
...
       Webpacker is installed ???? ????
       Using /tmp/build_1a3f514a6e7c53860f5484d15a8f3989/common-sense-Closer-1d0c0371331306325753abaf55f95f1de4d19c03/config/webpacker.yml file for setting up webpack paths
       [Webpacker] Compiling assets ????
       [Webpacker] Compiled digests for all packs in /tmp/build_1a3f514a6e7c53860f5484d15a8f3989/common-sense-Closer-1d0c0371331306325753abaf55f95f1de4d19c03/frontend/packs:
       {"application.css"=>"/packs/application-3c4c52abb78d77b81489.css", "application.css.map"=>"/packs/application-3c4c52abb78d77b81489.css.map", "application.js"=>"/packs/application-cb7d08695ec9c39428f7.js", "application.js.map"=>"/packs/application-cb7d08695ec9c39428f7.js.map", "fontawesome-webfont.eot"=>"/packs/fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot", "fontawesome-webfont.svg"=>"/packs/fontawesome-webfont-912ec66d7572ff821749319396470bde.svg", "fontawesome-webfont.ttf"=>"/packs/fontawesome-webfont-b06871f281fee6b241d60582ae9369b9.ttf", "fontawesome-webfont.woff"=>"/packs/fontawesome-webfont-fee66e712a8a08eef5805a46892932ad.woff", "fontawesome-webfont.woff2"=>"/packs/fontawesome-webfont-af7ae505a9eed503f8b8e6982036873e.woff2", "glyphicons-halflings-regular.eot"=>"/packs/glyphicons-halflings-regular-f4769f9bdb7466be65088239c12046d1.eot", "glyphicons-halflings-regular.svg"=>"/packs/glyphicons-halflings-regular-89889688147bd7575d6327160d64e760.svg", "glyphicons-halflings-regular.ttf"=>"/packs/glyphicons-halflings-regular-e18bbf611f2a2e43afc071aa2f4e1512.ttf", "glyphicons-halflings-regular.woff"=>"/packs/glyphicons-halflings-regular-fa2772327f55d8198301fdb8bcfc8158.woff", "glyphicons-halflings-regular.woff2"=>"/packs/glyphicons-halflings-regular-448c34a56d699c29117adc64c43affeb.woff2", "vendor.js"=>"/packs/vendor-b19a1da5cf018212c0bd.js", "vendor.js.map"=>"/packs/vendor-b19a1da5cf018212c0bd.js.map"}

The files are in the public/packs folder (I logged inside the heroku dyno to check):

~ $ ls public/packs/
application-3c4c52abb78d77b81489.css                 fontawesome-webfont-fee66e712a8a08eef5805a46892932ad.woff
application-3c4c52abb78d77b81489.css.gz              glyphicons-halflings-regular-448c34a56d699c29117adc64c43affeb.woff2
application-3c4c52abb78d77b81489.css.map             glyphicons-halflings-regular-89889688147bd7575d6327160d64e760.svg
application-cb7d08695ec9c39428f7.js              glyphicons-halflings-regular-89889688147bd7575d6327160d64e760.svg.gz
application-cb7d08695ec9c39428f7.js.gz               glyphicons-halflings-regular-e18bbf611f2a2e43afc071aa2f4e1512.ttf
application-cb7d08695ec9c39428f7.js.map              glyphicons-halflings-regular-e18bbf611f2a2e43afc071aa2f4e1512.ttf.gz
fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot     glyphicons-halflings-regular-f4769f9bdb7466be65088239c12046d1.eot
fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot.gz  glyphicons-halflings-regular-fa2772327f55d8198301fdb8bcfc8158.woff
fontawesome-webfont-912ec66d7572ff821749319396470bde.svg     manifest.json
fontawesome-webfont-912ec66d7572ff821749319396470bde.svg.gz  vendor-b19a1da5cf018212c0bd.js
fontawesome-webfont-af7ae505a9eed503f8b8e6982036873e.woff2   vendor-b19a1da5cf018212c0bd.js.gz
fontawesome-webfont-b06871f281fee6b241d60582ae9369b9.ttf     vendor-b19a1da5cf018212c0bd.js.map
fontawesome-webfont-b06871f281fee6b241d60582ae9369b9.ttf.gz

The manifest.json is as such:

{
  "application.css": "/packs/application-3c4c52abb78d77b81489.css",
  "application.css.map": "/packs/application-3c4c52abb78d77b81489.css.map",
  "application.js": "/packs/application-cb7d08695ec9c39428f7.js",
  "application.js.map": "/packs/application-cb7d08695ec9c39428f7.js.map",
  "fontawesome-webfont.eot": "/packs/fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot",
  "fontawesome-webfont.svg": "/packs/fontawesome-webfont-912ec66d7572ff821749319396470bde.svg",
  "fontawesome-webfont.ttf": "/packs/fontawesome-webfont-b06871f281fee6b241d60582ae9369b9.ttf",
  "fontawesome-webfont.woff": "/packs/fontawesome-webfont-fee66e712a8a08eef5805a46892932ad.woff",
  "fontawesome-webfont.woff2": "/packs/fontawesome-webfont-af7ae505a9eed503f8b8e6982036873e.woff2",
  "glyphicons-halflings-regular.eot": "/packs/glyphicons-halflings-regular-f4769f9bdb7466be65088239c12046d1.eot",
  "glyphicons-halflings-regular.svg": "/packs/glyphicons-halflings-regular-89889688147bd7575d6327160d64e760.svg",
  "glyphicons-halflings-regular.ttf": "/packs/glyphicons-halflings-regular-e18bbf611f2a2e43afc071aa2f4e1512.ttf",
  "glyphicons-halflings-regular.woff": "/packs/glyphicons-halflings-regular-fa2772327f55d8198301fdb8bcfc8158.woff",
  "glyphicons-halflings-regular.woff2": "/packs/glyphicons-halflings-regular-448c34a56d699c29117adc64c43affeb.woff2",
  "vendor.js": "/packs/vendor-b19a1da5cf018212c0bd.js",
  "vendor.js.map": "/packs/vendor-b19a1da5cf018212c0bd.js.map"
}

The problem is that inside the HTML of the page there is no link to them. Locally, in the development environment I have:

<link rel="stylesheet" media="screen" href="http://0.0.0.0:8080/packs/application.css" />

where I put the <%= stylesheet_pack_tag 'application' %> in the header.

In the staging environment on Heroku there is nothing in the HTML, hence it doesn't load the static assets.

Most helpful comment

@gauravtiwari I think I figured out my issue. I did a compile of assets using webpacker:

RAILS_ENV=production bundle exec rails webpacker:compile

and also added the following to my rails setup in config/environments/production.rb..

config.public_file_server.enabled = true

That seems to have fixed it.. I cannot seem to run webpacker on my production machines to automate the compilation but thats a separate issue related to nodejs.

Thanks for all the work on this!

All 16 comments

@rhymes Everything looks fine. Could you please try checking env from heroku console?

Webpacker::Env.current # OR 
Webpacker.env

# Lookup manifest manually
Webpacker::Manifest.lookup('application.js')

BTW you don't have to setup staging env for webpacker. It can just use production.

Here it is:

irb(main):001:0> Webpacker::Env.current
=> "staging"
irb(main):002:0> Webpacker.env
=> "staging"
irb(main):003:0> Webpacker::Manifest.lookup('application.js')
=> "/packs/application-e2c68848d22eb7345084.js"
irb(main):004:0>

same issue though i'm deploying on kubernetes.. webpacker works in development but not in production

I get a 404 for the application-hash32749.js in chrome

@34code Have you compiled the assets during deployment? - RAILS_ENV=production bundle exec rails webpacker:compile. Also, if you could post relevant deployment logs and how does your manifest.json looks it would be helpful to figure out the problem.

@rhymes I will try to reproduce this issue on Heroku. You are still seeing the same problem right?

@gauravtiwari yeah.

I also tried just now using multiple buildpacks to specify NodeJS and Yarn versions, like it says here: https://devcenter.heroku.com/articles/ruby-support#installed-binaries

This is the build log:

-----> Node.js app detected
-----> Creating runtime environment

       NPM_CONFIG_LOGLEVEL=error
       NPM_CONFIG_PRODUCTION=true
       NODE_VERBOSE=false
       NODE_ENV=production
       NODE_MODULES_CACHE=true
-----> Installing binaries
       engines.node (package.json):  >=7.0.0
       engines.npm (package.json):   unspecified (use default)

       Resolving node version >=7.0.0 via semver.io...
       Downloading and installing node 8.1.0...
       Using default npm version: 5.0.3
       Downloading and installing yarn (0.24.6)...
       Installed yarn 0.24.6
-----> Restoring cache
       Skipping cache restore (new-signature)
-----> Building dependencies
       Installing node modules (yarn.lock)
       yarn install v0.24.6
       warning No license field
       [1/4] Resolving packages...
       [2/4] Fetching packages...
       warning [email protected]: The platform "linux" is incompatible with this module.
       info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
       [3/4] Linking dependencies...
       [4/4] Building fresh packages...
       $ npm rebuild node-sass

       > [email protected] install /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       > node scripts/install.js

       node-sass build Binary found at /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass/vendor/linux-x64-57/binding.node

       > [email protected] postinstall /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       > node scripts/build.js

       Binary found at /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass/vendor/linux-x64-57/binding.node
       Testing binary
       Binary is fine
       [email protected] /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       Done in 69.64s.
-----> Caching build
       Clearing previous node cache
       Saving 2 cacheDirectories (default):
       - node_modules
       - bower_components (nothing to cache)

[ALL THE RUBY PART]

-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       yarn install v0.24.6
       warning No license field
       [1/4] Resolving packages...
       [2/4] Fetching packages...
       warning [email protected]: The platform "linux" is incompatible with this module.
       info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
       [3/4] Linking dependencies...
       [4/4] Building fresh packages...
       $ npm rebuild node-sass
       > [email protected] install /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       > node scripts/install.js
       Downloading binary from https://github.com/sass/node-sass/releases/download/v4.5.3/linux-x64-57_binding.node
       Download complete
       Binary saved to /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass/vendor/linux-x64-57/binding.node
       Caching binary to /app/.npm/node-sass/4.5.3/linux-x64-57_binding.node
       > [email protected] postinstall /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       > node scripts/build.js
       Binary found at /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass/vendor/linux-x64-57/binding.node
       Testing binary
       Binary is fine
       [email protected] /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/node_modules/node-sass
       Done in 12.56s.
       Webpacker is installed ???? ????
       Using /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/config/webpacker.yml file for setting up webpack paths
       [Webpacker] Compiling assets ????
       [Webpacker] Compiled digests for all packs in /tmp/build_57d11b86afbb604917d55f61aa4dae9a/common-sense-Closer-a8be24716a1941eb6775d4fd3e2c66163eb5ad50/frontend/packs:
       {"application.css"=>"/packs/application.css", "application.css.map"=>"/packs/application.css.map", "application.js"=>"/packs/application-f456934f3f3422c8b38b.js", "application.js.map"=>"/packs/application-f456934f3f3422c8b38b.js.map", "fontawesome-webfont.eot"=>"/packs/fontawesome-webfont.eot", "fontawesome-webfont.svg"=>"/packs/fontawesome-webfont.svg", "fontawesome-webfont.ttf"=>"/packs/fontawesome-webfont.ttf", "fontawesome-webfont.woff"=>"/packs/fontawesome-webfont.woff", "fontawesome-webfont.woff2"=>"/packs/fontawesome-webfont.woff2", "glyphicons-halflings-regular.eot"=>"/packs/glyphicons-halflings-regular.eot", "glyphicons-halflings-regular.svg"=>"/packs/glyphicons-halflings-regular.svg", "glyphicons-halflings-regular.ttf"=>"/packs/glyphicons-halflings-regular.ttf", "glyphicons-halflings-regular.woff"=>"/packs/glyphicons-halflings-regular.woff", "glyphicons-halflings-regular.woff2"=>"/packs/glyphicons-halflings-regular.woff2", "vendor.js"=>"/packs/vendor-d7e64ddb898cda9fc461.js", "vendor.js.map"=>"/packs/vendor-d7e64ddb898cda9fc461.js.map"}
       Asset precompilation completed (70.13s)
       Cleaning assets
       Running: rake assets:clean

BTW this is my package json:

{
  "engines": {
     "node": ">=7.0.0",
     "yarn": "0.24.6"
  },
  "scripts": {
    "postinstall": "npm rebuild node-sass"
  },
  "devDependencies": {
    "bower": "^1.8.0",
    "webpack-dev-server": "^2.4.5"
  },
  "dependencies": {
    "autoprefixer": "^7.1.1",
    "awesome-bootstrap-checkbox": "0.3.7",
    "babel-core": "^6.24.1",
    "babel-loader": "7.x",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-polyfill": "^6.23.0",
    "babel-preset-env": "^1.5.2",
    "blueimp-load-image": "^2.12.2",
    "bootbox": "^4.4.0",
    "bootstrap": "^3.3.7",
    "bootstrap-sass": "^3.3.7",
    "chart.js": "^2.6.0",
    "compression-webpack-plugin": "^0.4.0",
    "cropper": "^3.0.0-rc.2",
    "css-loader": "^0.28.4",
    "datatables.net": "^1.10.15",
    "datatables.net-bs": "^1.10.15",
    "datatables.net-plugins": "^1.10.15",
    "extract-text-webpack-plugin": "^2.1.2",
    "file-loader": "^0.11.2",
    "font-awesome": "^4.7.0",
    "glob": "^7.1.2",
    "handsontable": "^0.32.0",
    "html5-history-api": "^4.2.8",
    "imports-loader": "^0.7.1",
    "jQuery-QueryBuilder": "^2.4.3",
    "jquery": "2.2.4",
    "jquery-datetimepicker": "^2.5.4",
    "jquery-extendext": "^0.1.2",
    "jquery-readyselector": "https://github.com/askehansen/jquery-readyselector.git",
    "jquery-ujs": "^1.2.2",
    "js-cookie": "^2.1.4",
    "js-yaml": "^3.8.4",
    "jstz": "^1.0.9",
    "lodash": "^4.17.4",
    "moment": "^2.18.1",
    "moment-timezone": "^0.5.13",
    "node-sass": "^4.5.3",
    "path-complete-extname": "^0.1.0",
    "postcss-loader": "^2.0.5",
    "postcss-smart-import": "^0.7.4",
    "precss": "^1.4.0",
    "rails-erb-loader": "^5.0.1",
    "rails-timezone": "^1.0.0",
    "resolve-url-loader": "^2.0.2",
    "sass-loader": "^6.0.5",
    "script-loader": "^0.7.0",
    "selectize": "^0.12.4",
    "store": "^2.0.4",
    "style-loader": "^0.18.2",
    "urijs": "^1.18.10",
    "webpack": "^2.6.1",
    "webpack-manifest-plugin": "^1.1.0",
    "webpack-merge": "^4.1.0"
  }
}

@rhymes Strange! I just deployed an app to Heroku and it's working fine - https://webpacker-example-app.herokuapp.com/.

From logs, I see the build has succeeded and outputted the bundles and manifest. Lets check your rails views - what you got there? Just to confirm you are using Webpacker from master or 2.0? Have you upgraded lately?

@gauravtiwari you can find the app here https://cs-closer-dev-pr-15.herokuapp.com/users/sign_in as you can see the HTML of the sign in page has no <link> to the files created in the json manifest. I checked again inside the heroku app and the files are there:

~ $ ls public/packs/
application.css              fontawesome-webfont.eot.gz  glyphicons-halflings-regular.eot     manifest.json
application.css.gz           fontawesome-webfont.svg     glyphicons-halflings-regular.svg     vendor-d7e64ddb898cda9fc461.js
application.css.map          fontawesome-webfont.svg.gz  glyphicons-halflings-regular.svg.gz  vendor-d7e64ddb898cda9fc461.js.gz
application-f456934f3f3422c8b38b.js  fontawesome-webfont.ttf     glyphicons-halflings-regular.ttf     vendor-d7e64ddb898cda9fc461.js.map
application-f456934f3f3422c8b38b.js.gz   fontawesome-webfont.ttf.gz  glyphicons-halflings-regular.ttf.gz
application-f456934f3f3422c8b38b.js.map  fontawesome-webfont.woff    glyphicons-halflings-regular.woff
fontawesome-webfont.eot          fontawesome-webfont.woff2   glyphicons-halflings-regular.woff2
~ $ cat public/packs/manifest.json
{
  "application.css": "/packs/application.css",
  "application.css.map": "/packs/application.css.map",
  "application.js": "/packs/application-f456934f3f3422c8b38b.js",
  "application.js.map": "/packs/application-f456934f3f3422c8b38b.js.map",
  "fontawesome-webfont.eot": "/packs/fontawesome-webfont.eot",
  "fontawesome-webfont.svg": "/packs/fontawesome-webfont.svg",
  "fontawesome-webfont.ttf": "/packs/fontawesome-webfont.ttf",
  "fontawesome-webfont.woff": "/packs/fontawesome-webfont.woff",
  "fontawesome-webfont.woff2": "/packs/fontawesome-webfont.woff2",
  "glyphicons-halflings-regular.eot": "/packs/glyphicons-halflings-regular.eot",
  "glyphicons-halflings-regular.svg": "/packs/glyphicons-halflings-regular.svg",
  "glyphicons-halflings-regular.ttf": "/packs/glyphicons-halflings-regular.ttf",
  "glyphicons-halflings-regular.woff": "/packs/glyphicons-halflings-regular.woff",
  "glyphicons-halflings-regular.woff2": "/packs/glyphicons-halflings-regular.woff2",
  "vendor.js": "/packs/vendor-d7e64ddb898cda9fc461.js",
  "vendor.js.map": "/packs/vendor-d7e64ddb898cda9fc461.js.map"
}

They are just not linked in the HTML, it's like the statements

<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'vendor' %>
<%= javascript_pack_tag 'application' %>

return emptry strings on staging/production.

I am using webpacker 2.0, Rails 4.2.8 and Ruby 2.3.4.

Let me try to upgrade to master and see what happens

@gauravtiwari I think I figured out my issue. I did a compile of assets using webpacker:

RAILS_ENV=production bundle exec rails webpacker:compile

and also added the following to my rails setup in config/environments/production.rb..

config.public_file_server.enabled = true

That seems to have fixed it.. I cannot seem to run webpacker on my production machines to automate the compilation but thats a separate issue related to nodejs.

Thanks for all the work on this!

@gauravtiwari I tried also with master but with no luck :(

Thanks again for the helpful tips. I think there's something wrong with my configuration somewhere but I'm not quite sure about what it is

@34code Awesome 馃憤 Thanks for sharing back. @rhymes Could you please check if your problem is same? - config.public_file_server.enabled = true (but I am pretty sure Heroku sets this). Please double check heroku env vars.

@gauravtiwari yeah it's set by the rails_12factor gem which requires the gem rails_server_static_assets which does that according to each Rails version https://github.com/heroku/rails_serve_static_assets/blob/master/lib/rails_serve_static_assets/railtie.rb#L5

In my Gemfile I have this:

group :production, :staging do
  gem 'heroku-deflater', '0.6.3'# Deflate assets on heroku
  gem 'rack-timeout', '0.4.2'   # Rack middleware which aborts requests that have been running for longer than a specified timeout.
  gem 'rails_12factor', '0.0.3' # Run Rails the 12factor way
end

These are my relevant heroku env vars:

LANG='en_US.UTF-8'
RACK_ENV=staging
RAILS_ENV=staging
RAILS_SERVE_STATIC_FILES=enabled

If that weren't the case I would not be getting the "sprockets" static files as well but those are accessible

@rhymes Yepp 馃憤

Could you try static HTML tag with asset_pack_path helper? Or you can even use Webpacker::Manifest.lookup - https://github.com/rails/webpacker/blob/master/lib/webpacker/helper.rb#L11

```erb