Here’s an nice article from Arkency on configuring Rails with Webpack:
Creating custom Heroku buildpack for Webpack and Ruby on Rails integration
I’m going to compare this to how we configure react-webpack-rails-tutorial, live example at reactrails.com.
The article does a fine job of explaining how to create a custom buildpack to solve the Rails + Webpack deployment problem.
At ShakaCode, we took a different approach:
- Some changes to our app
- Using the standard node buildpack
The article assumes the following about the application structure. Below each quoted bullet, I describe how our technique is different.
NOTE quoted sections like this are from the Arkency article.
package.json (one or two)
- The Node.js package.json resides under app/assets within the Rails application root.
We create a top level package.json containing:
"scripts": {
"postinstall": "cd client && npm install",
"test": "rspec && (cd client && npm run lint)"
},
The default node.js buildpack depends on the top level package.json.
Where We Put Our Client Code
- Source files are stored under app/assets/source.
We use /app/client/app
. This allows us to have the client app be isolated from the Rails app.
Manifest file for JavaScript
- Webpack compiles the bundle into app/assets/javascripts directory and this bundle is required within application manifest (application.js)
We do the same thing in application.js:
//= require generated/vendor-bundle
//= require generated/app-bundle
devDependencies and the NODE_ENV
- Webpack, Babel and loaders are installed as devDependencies so they are not installed if Node.js environment is set to production.
- All JavaScript dependencies of the codebase are installed on the Node.js side as regular dependencies.
- There is a npm script named build-production that creates the production-ready bundle (by production-ready I mean - deduped one)
We take a different approach:
- Add all build tools that heroku needs to dependencies. Since Webpack will strip out anything that is not referenced in the bundles, this is not problem.
- Configure our webpack.client.rails.config to depend on the NODE_ENV. Thus we have just one script for Rails.
This is how we determine if we’re doing a “devBuild”:
const devBuild = process.env.NODE_ENV !== 'production';