How can I use webpack with express?
Solution 1
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'
}
;
Solution 2
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',
},
}
];
Solution 3
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'
}
Solution 4
Additionally, if you are working with Typescript, make sure to also include the ".js" extension in your config:
module.exports = {
entry: './src/server/index.ts',
target: 'node',
output: {
path: __dirname + '/dist/server',
filename: 'bundle.js',
},
resolve: {
modules: [
"node_modules"
],
extensions: [".ts", ".js"]
}
};
Solution 5
I took an easy approach that could be useful in a small or medium project. I make it so webpack would serve as the bundler for ecma script and scss, though in this aproach i dont use hot reloading.
The server configuration is the default given by express generator.
webpack.config.js
const path = require("path");
module.exports = {
entry: "./resources/index.js",
output: {
path: path.join(__dirname, "/public/dist"),
publicPath: "/public/dist",
filename: "main.js"
},
mode: "development",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
}
};
package.json is devDependencies
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/preset-env": "^7.6.3",
"babel-loader": "^8.0.6",
"css-loader": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9"
}
package.json is scripts
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon",
"build": "webpack",
"watch": "webpack --watch"
},
Comments
-
SudoPlz over 2 years
When I try to use webpack with a simple express server I always get TONS of errors: express.js
'use strict'; var express = require('express'); var path = require('path'); var url = require('url'); // -------- my proxy---------------------- var app = express(); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.set('port', process.env.PORT || 8080); app.use(function logErrors(err, req, res, next) { console.error(err.stack); next(err); } ); app.listen(app.get('port'), function() { console.info('Express server started at http://localhost:' + app.get('port')); });
I get all those errors:
Version: webpack 1.10.0 Time: 1200ms Asset Size Chunks Chunk Names outfile 559 kB 0 [emitted] main chunk {0} outfile (main) 498 kB [rendered] [0] ../app/server/express2.js 553 bytes {0} [built] + 125 hidden modules WARNING in ../~/express/lib/view.js Critical dependencies: 78:29-56 the request of a dependency is an expression @ ../~/express/lib/view.js 78:29-56 ERROR in ../~/express/lib/request.js Module not found: Error: Cannot resolve module 'net' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/lib @ ../~/express/lib/request.js 18:11-25 ERROR in ../~/express/lib/view.js Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/lib @ ../~/express/lib/view.js 18:9-22 ERROR in ../~/express/~/send/index.js Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send @ ../~/express/~/send/index.js 25:9-22 ERROR in ../~/express/~/etag/index.js Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/etag @ ../~/express/~/etag/index.js 22:12-25 ERROR in ../~/express/~/send/~/destroy/index.js Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/destroy @ ../~/express/~/send/~/destroy/index.js 1:17-30 ERROR in ../~/express/~/send/~/mime/mime.js Module not found: Error: Cannot resolve module 'fs' in /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/mime @ ../~/express/~/send/~/mime/mime.js 2:9-22 ERROR in ../~/express/~/send/~/statuses/codes.json Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/statuses/codes.json Line 2: Unexpected token : You may need an appropriate loader to handle this file type. | { | "100": "Continue", | "101": "Switching Protocols", | "102": "Processing", @ ../~/express/~/send/~/statuses/index.js 2:12-35 ERROR in ../~/express/~/send/~/mime/types.json Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/send/node_modules/mime/types.json Line 1: Unexpected token : You may need an appropriate loader to handle this file type. | @ ../~/express/~/send/~/mime/mime.js 87:12-35 ERROR in ../~/express/~/accepts/~/mime-types/~/mime-db/db.json Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/accepts/node_modules/mime-types/node_modules/mime-db/db.json Line 2: Unexpected token : You may need an appropriate loader to handle this file type. | { | "application/1d-interleaved-parityfec": { | "source": "iana" | }, @ ../~/express/~/accepts/~/mime-types/~/mime-db/index.js 11:17-37 ERROR in ../~/express/~/type-is/~/mime-types/~/mime-db/db.json Module parse failed: /Users/Dynopia/Development/DS_Stalker_Frontend/node_modules/express/node_modules/type-is/node_modules/mime-types/node_modules/mime-db/db.json Line 2: Unexpected token : You may need an appropriate loader to handle this file type. | { | "application/1d-interleaved-parityfec": { | "source": "iana" | }, @ ../~/express/~/type-is/~/mime-types/~/mime-db/index.js 11:17-37
and this is my config file:
var webpack = require('webpack'); module.exports = { // Makes sure errors in console map to the correct file // and line number devtool: 'eval', entry: [ './bin/www.js' ], output: { path: './bin/out', filename: 'server.js' }, extensions: [ '', '.jsx', '.js' ], module: { loaders: [ // Compile es6 to js. { test: /app\/.*\.js?$/, loaders: [ 'react-hot', 'babel-loader' ] } ] }, devtool: 'source-map' };
What can I do, I need to use webpack on my server side as well.
I run the express.js file like so:
./node_modules/webpack/bin/webpack.js ../app/server/express.js outfile --display-chunks -c --progress -d
-
jdahlgren almost 9 yearsDo you have a source for using multiple configurations in a single file? I couldn't find it in Webpack docs and it's not working for me.
-
Admin over 8 yearsAlthough I couldn't find docs, an example exists in the repository: github.com/webpack/webpack/tree/master/examples/multi-compiler
-
Ateev Chopra over 8 yearsCan you please share where you add webpack into node file ? That would be helpful.
-
SudoPlz over 8 yearsNot sure if I understood your question correctly, but if I did, you don't add webpack into your main node file. Webpack converts your node file, but you don't have to put webpack code IN it. You just convert the file using webpack command line before running your main file with node. In my case I ran the whole thing by typing
npm start debugMode
.deugMode
was a script I created to do everything for me, here is a part of mypackage.json
code: tinyurl.com/tldrsudo -
Eldelshell over 8 yearsMan this is the sort of magic I love. That little nodeModules thing made my day.
-
Marco Lazzeri over 8 yearsStill failing for me when trying to load the
express/lib/view.js
dependency (the request of a dependency is an expression @ ../~/express/lib/view.js 78:29-56
) -
tet about 8 yearsHI, I'm trying to figure out your webpack set-up. Could you tell me the file name of your server webpack config? I would like to know how you built your ./app/server/serverEntryPrototype.js into ./bin/serverEntryPrototype.js.
-
SudoPlz about 8 yearsI updated my answer to include the filenames of each file, I hope that helps.
-
tet about 8 years@SudoPlz thank you so much for adding the filenames, now I'm having webpack and express working together. You rock, sir!!
-
Joseph Rex about 8 yearsSo when you change an asset (scss, css, js) you have to stop your express server to separately run webpack for browser assets? or how do you go about it?
-
alfonsodev over 7 yearsbare in mind with private orgs, the packages are installed under node_modules/@organisation/packageName so you must add them "manually" right after readdirSync. With `nodeModules['@myorg/mypackage'] = 'commonjs mypackage'
-
Alexander over 7 yearseverything is working for me but when I introduced require express, webpack now gives me a ton of error.. this solves it.. now upvoted
-
Abdulhakim over 2 yearsAfter you finish the code, on the command line, just type: "npm run dev"