Skip to content

Instantly share code, notes, and snippets.

@jwietelmann
Last active November 23, 2019 17:35
Show Gist options
  • Save jwietelmann/31de828c6df358c192a8 to your computer and use it in GitHub Desktop.
Save jwietelmann/31de828c6df358c192a8 to your computer and use it in GitHub Desktop.
File that exports separate webpack configs for frontend and backend
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var deepMerge = require('deep-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
// BEGIN CONFIG TOOLS
// Set up config merging function.
var merge = deepMerge(function(target, source, key) {
if(target instanceof Array) {
return [].concat(target, source);
}
return source;
});
// Create default config.
var defaultConfig = {
module: {
output: {
// Treat this as being relative to package.json.
// So basically our project directory.
path: './',
},
loaders: [
{
// Run all JavaScript through Babel with our favorite presets.
test: /\.js$/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-0'],
},
// Skip node_modules and bower_components directories.
// Those shouldn't need to run through Babel.
exclude: /(node_modules|bower_components)/,
},
],
},
// `source-map-support` causes problems unless you keep this out of the bundle.
node: {
fs: 'empty',
}
};
// Add debugging things in non-prod environments.
if(process.env.NODE_ENV !== 'production') {
defaultConfig.devtool = 'source-map';
defaultConfig.debug = true;
}
// Convenience function for extending default config.
function config(overrides) {
return merge(defaultConfig, overrides || {});
}
// END CONFIG TOOLS
// BEGIN FRONTEND CONFIGURATION
// Complete frontend configuration object.
var frontendConfig = config({
entry: './webpack/src/client.js',
output: {
filename: 'app/assets/javascripts/application.js'
},
module: {
loaders: [
{
test: /\.(sass|scss)$/,
// It is very, very important that this be defined exactly this way.
// For example, this would cause the npm path resolver to stop working,
// even though it would otherwise work:
//
// `ExtractTextPlugin.extract('style-loader', 'css-loader', 'sass-loader')`
//
// SO DON'T TOUCH THIS UNLESS YOU KNOW WHAT YOU'RE DOING.
//
// Oh, so anyway, this is the thing that instead of inlining the styles
// extracts them into a separate CSS file.
loader: ExtractTextPlugin.extract('style-loader', 'css!sass'),
},
],
},
plugins: [
// Point the extracted CSS at the correct output file.
new ExtractTextPlugin('app/assets/stylesheets/application.css'),
],
});
// END FRONTEND CONFIGURATION
// BEGIN BACKEND CONFIGURATION
// Find node modules and make them external dependencies for the backend build.
// Otherwise you'll bundle up a ton of stuff you don't need to.
var externals = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
externals[mod] = 'commonjs ' + mod;
});
// Complete backend configuration object.
var backendConfig = config({
entry: './webpack/src/server.js',
output: {
filename: 'webpack/build/server.js'
},
// This is how webpack knows to compile for Node.js and not the browser.
target: 'node',
// Remember that list of node modules we just built?
// This is us telling webpack not to bundle them.
externals: externals,
plugins: [
// For frontend builds we use `import './something.scss'` to include a style dependency.
// Which works because of `sass-loader`.
// We don't use that for backend.
// This plugin ensures those imports don't cause runtime errors server-side.
new webpack.NormalModuleReplacementPlugin(/\.(css|scss|sass)/, 'node-noop'),
],
});
// END BACKEND CONFIGURATION
// Export these configs.
exports.frontend = frontendConfig;
exports.backend = backendConfig;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment