How can I use webpack with express?
It can be realized by specifying "node" to "target" option, since v1.10.2.
For reference: http://jlongster.com/Backend-Apps-with-Webpack--Part-I
If you want to bundle the server and the client's code at the same time, it is possible to use multiple configuration in the following manner.
// webpack.config.js
module.exports = [
{
name: 'server',
entry: './src/server/index.js',
target: 'node',
output: {
path: __dirname + '/dist/server',
filename: 'bundle.js',
},
},
{
name: 'client',
entry: './src/client/index.js',
// target: 'web', // by default
output: {
path: __dirname + '/dist/client',
filename: 'bundle.js',
},
}
];
I am just clarifying @meta2's answer because I believe it can be written in a more understandable way - although full points to him!
tl;dr - set target: 'node'
in your webpack.config.js
to fix the errors that get generated when using Webpack with Express.
You still get warnings like:
WARNING in ./node_modules/express/lib/view.js
81:13-25 Critical dependency: the request of a dependency is an expression
To fix those, use https://github.com/liady/webpack-node-externals. FYI - this reduces you bundle size significantly (check size before and after) and speeds up the bundling time incredibly.
Full example:
const path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: './src/app.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
target: 'node', // THIS IS THE IMPORTANT PART
externals: [nodeExternals()],
mode: 'development'
}
What I ended up doing was I used 2 different configurations, 1 for packing the server stuff together using webpack, and 1 for packing all the browser stuff together and also run webpack dev server for hot reloading.
Server webpack config aka webpack.node.config.js
now looks like this:
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
// note the path.resolve(__dirname, ...) part
// without it, eslint-import-resolver-webpack fails
// since eslint might be invoked with different cwd
fs.readdirSync(path.resolve(__dirname, 'node_modules'))
.filter(x => ['.bin'].indexOf(x) === -1)
.forEach(mod => { nodeModules[mod] = `commonjs ${mod}`; });
// es5 style alternative
// fs.readdirSync(path.resolve(__dirname, 'node_modules'))
// .filter(function(x) {
// return ['.bin'].indexOf(x) === -1;
// })
// .forEach(function(mod) {
// nodeModules[mod] = 'commonjs ' + mod;
// });
module.exports =
{
// The configuration for the server-side rendering
name: 'server',
target: 'node',
entry: './app/server/serverEntryPrototype.js',
output: {
path: './bin/',
publicPath: 'bin/',
filename: 'serverEntryPoint.js'
},
externals: nodeModules,
module: {
loaders: [
{ test: /\.js$/,
loaders: [
// 'imports?document=this',
// 'react-hot',
'babel-loader'
//,'jsx-loader'
]
},
{ test: /\.json$/, loader: 'json-loader' },
]
},
plugins: [
// new webpack.NormalModuleReplacementPlugin("^(react-bootstrap-modal)$", "^(react)$")
// new webpack.IgnorePlugin(new RegExp("^(react-bootstrap-modal)$"))
// new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
]
};
Browser webpack config aka webpack.browser.config.js
now looks like this:
var webpack = require('webpack');
var path = require('path');
var buildPath = path.resolve(__dirname, 'assets');
var fs = require('fs');
var commonLoaders = [
{ test: /\.js$/,
loaders: [
'react-hot',
'babel-loader'
//,'jsx-loader'
]
}
];
module.exports =
{
// Makes sure errors in console map to the correct file
// and line number
name: 'browser',
devtool: 'eval',
entry: [
//'./bin/www.js',
'./app/index.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8081' // WebpackDevServer host and port
],
output: {
path: buildPath,
filename: '[name].js',
// Everything related to Webpack should go through a build path,
// localhost:3000/build. That makes proxying easier to handle
publicPath: 'http://localhost:8081/assets/'
},
extensions: [
'',
'.jsx', '.js',
'.json',
'.html',
'.css', '.styl', '.scss', '.sass'
],
module: {
loaders: [
// Compile es6 to js.
{
test: /app\/.*\.jsx?$/,
loaders: [
'react-hot',
'babel-loader'
]
},
///app\/.*\.json$/
{ test: /\.json$/, loader: 'json-loader' },
// Styles
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.s(a|c)ss$/, loader: 'style!css?localIdentName=[path][name]---[local]---[hash:base64:5]!postcss!sass' },
// Fonts
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff' },
{ test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader' }
//{ test: /\.png$/, loader: 'url-loader?limit=100000' },
//{ test: /\.jpg$/, loader: 'file-loader' }
],
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
},
postcss: [
require('autoprefixer-core')
],
devtool: 'source-map'
}
;