Mysterious build failures on Heroku (no error details, css-loader somehow involved)

Disclaimer: this is probably not an issue with Webpack but rather an issue with Heroku (it fails only on Heroku), but main reason of posting here is to get some directions of how we could localize the issue, because Webpack prints zero error messages just silently fails.

We also think that the problem somehow related to CSS compilation in particular. First we run into this issue after upgrading css-loader to v0.19, and we decided to use css-loader@0.18 temporarily. But then, after we had more CSS, we run into the same issue with 0.18. We switched to paid plan on Heroku, which allowed us to build using css-loader@0.18 (not 0.19+ though) for a while, but then, after we wrote more CSS, the issue came back again.

We build our front-end code on Heroku, specifically by running following command in “postinstall” npm script:

webpack --config webpack-stage.config.js --progress --profile --colors --display-error-details --debug

And we get the following output from Heroku:

Deploying application
creating application archive
uploading application archive
triggering new deployment
-----> Fetching custom buildpack https://github.com/heroku/heroku-buildpack-multi.git... done
-----> Multipack app detected
=====> Downloading Buildpack: https://github.com/debitoor/ssh-private-key-buildpack.git
=====> Detected Framework: SSH private key
-----> Running SSH private key setup
       Warning: Permanently added 'github.com,~some IP address~' (RSA) to the list of known hosts.
       Hi ***! You've successfully authenticated, but GitHub does not provide shell access.
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs.git
=====> Detected Framework: Node.js
-----> Creating runtime environment

       NPM_CONFIG_LOGLEVEL=error
       NPM_CONFIG_PRODUCTION=true
       NODE_ENV=staging
       NODE_MODULES_CACHE=true

       npm scripts will see NODE_ENV=production (not 'staging')
       https://docs.npmjs.com/misc/config#production
-----> Installing binaries
       engines.node (package.json):  4.x.x
       engines.npm (package.json):   2.x.x

       Resolving node version 4.x.x via semver.io...
       Downloading and installing node 4.2.1...
       Resolving npm version 2.x.x via semver.io...
       Downloading and installing npm 2.14.8 (replacing version 2.14.7)...
-----> Restoring cache
       Loading 2 from cacheDirectories (default):
       - node_modules
       - bower_components (not cached - skipping)
-----> Building dependencies
       Pruning any extraneous modules
       Installing node modules (package.json)

       > onlineeducation-frontend@0.0.0 postinstall /tmp/build_ed2ac827f93d7fb13a64bdfc659f6f28
       > if [ "$HEROKU" = "1" ]; then npm run build-stage ; fi


       > onlineeducation-frontend@0.0.0 build-stage /tmp/build_ed2ac827f93d7fb13a64bdfc659f6f28
       > webpack --config webpack-stage.config.js --progress --profile --colors --display-error-details --debug

 31%% 125/353 build modulesContainer#eachAtRule is deprecated. Use Container#walkAtRules instead.
       Container#eachRule is deprecated. Use Container#walkRules instead.
       Container#eachDecl is deprecated. Use Container#walkDecls instead.
 41%% 192/363 build modulesNode#before is deprecated. Use Node#raws.before
       Node#removeSelf is deprecated. Use Node#remove.
 65%% 940/101
-----> Build failed

       We're sorry this build is failing! You can troubleshoot common issues here:
       https://devcenter.heroku.com/articles/troubleshooting-node-deploys

       If you're stuck, please submit a ticket so we can help:
       https://help.heroku.com/

       Love,
       Heroku

 !     Push rejected, failed to compile Multipack app

Also Heroku sometimes prints this line:

couldn't write 98058 items to stdout: Resource temporarily unavailable

Here is how our config looks like (stripped out a bit, but all important parts should be in place):

var path = require('path')
var webpack = require('webpack')
var StatsPlugin = require('stats-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

var root = path.join(__dirname, 'app')

var excludeFromStats = [
  /node_modules/,
]

var plugins = []

var globals = {
  __PRERENDER__: JSON.stringify(false || false),
  __DEV__: JSON.stringify(true),
  'process.env.NODE_ENV': JSON.stringify('development'),
}

var cssLoader = '?disableStructuralMinification&modules'
  + '&localIdentName=[name]__[local]__[hash:base64:5]'
  + '!autoprefixer!stylus'

cssLoader = ExtractTextPlugin.extract('style', 'css' + cssLoader)
plugins.push(
  new ExtractTextPlugin('[name].css?[contenthash]')
)

plugins.push(
  new StatsPlugin(path.join(__dirname, 'build', 'stats.json'), {
    chunkModules: true,
    exclude: excludeFromStats,
    source: false,
  })
)

plugins.push(new webpack.DefinePlugin(globals))



var entry = {
  main: ['./build-entries/in-browser'],
}
entry.lib = ['./build-entries/in-browser-lib']
entry.admin = ['./build-entries/admin-panel.js']

Object.keys(entry).forEach(function(key) {
  entry[key].unshift('babel-core/polyfill')
})

var output = {
  path: path.join(__dirname, 'build', false ? 'prerender' : 'public'),
  publicPath: '/_assets/',
  filename: '[name].js?[chunkhash]',
  pathinfo: true,
}

var _module = {
  loaders: [
    {test: /\.jsx$/, loader: false ? 'react-hot!babel' : 'babel'},
    {test: /\.js$/, loader: 'babel', include: [
      path.join(__dirname, 'app'),
      path.join(__dirname, 'build-entries'),
      path.join(__dirname, 'mocks'),
      path.join(__dirname, 'lib'),
    ]},
    {test: /\.json$/, loader: 'json'},
    {test: /\.(png|gif)$/, loader: 'url?name=[name]@[hash].[ext]&limit=5000'},
    {test: /\.(jpg|otf|woff|ttf|mp4|webm)$/, loader: 'file?name=[name]@[hash].[ext]'},
    {test: /\.styl$/, loader: cssLoader},
  ],
}

var resolve = {
  root: root,
  extensions: ['', '.js', '.jsx'],
  alias: {
    '#mocks': path.join(__dirname, 'mocks'),
    '#lib': path.join(__dirname, 'lib'),
  },
}

var devServer = {
  stats: {
    cached: false,
    exclude: excludeFromStats,
  },
}

var stylus = {
  import: [
    path.join(__dirname, 'app', 'global-styles', 'vars.styl'),
  ],
}

module.exports = {
  entry: entry,
  output: output,
  target: false ? 'node' : 'web',
  module: _module,
  debug: true,
  bail: true,
  resolve: resolve,
  plugins: plugins,
  devServer: devServer,
  stylus: stylus,
}

Any help highly appreciated!

Author: Fantashit

4 thoughts on “Mysterious build failures on Heroku (no error details, css-loader somehow involved)

  1. i had the same issue, try to remove the –progress flag from webpack command, its worked for me.
    looks like heroku stop and failed the build if its prints too many logs.

  2. Can confirm. --progress is the culprit. With it, a webpack build exits without any helpful information.

  3. --progress will be a problem (it’s designed for an interactive terminal and has no reasonable fallback for a non-interactive session like a build on Heroku).

    Other issues I’ve seen with webpack builds include anything that forks child processes to run things in parallel. (the bash equivalent is build foo & build bar). At Heroku, our build system waits for an exit code from the top level process. If you fork parallel work, it’s not guaranteed to finish before the top level process does, leading to a situation where your build may or may not succeed.

Comments are closed.