46

I've been trying to use webpack with a nodejs application, and the client side is going fine - a reasonably good documentation on their website + links from google search.

Has anyone used webpack on server side of nodejs? or please guide me to any useful links.

Thanks.

user237865
  • 1,250
  • 4
  • 19
  • 41

3 Answers3

32

This might be useful: http://jlongster.com/Backend-Apps-with-Webpack--Part-I

Key point is to make external all third party module (in node_modules directory) in webpack config file

Final config file

var webpack = require('webpack');
var path = require('path');
var fs = require('fs');

var nodeModules = {};
fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs ' + mod;
  });

module.exports = {
  entry: './src/main.js',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'backend.js'
  },
  externals: nodeModules,
  plugins: [
    new webpack.IgnorePlugin(/\.(css|less)$/),
    new webpack.BannerPlugin('require("source-map-support").install();',
                             { raw: true, entryOnly: false })
  ],
  devtool: 'sourcemap'
}
Olim Saidov
  • 2,796
  • 1
  • 25
  • 32
26

A real example with webpack 2.x

I want to highlight the difference from client side config:

1. target: 'node'

2. externals: [nodeExternals()]

for node.js, it doesn't make much sense to bundle node_modules/

3. output.libraryTarget: 'commonjs2'

without this, you cannot require('your-library')

webpack.config.js

import nodeExternals from 'webpack-node-externals'

const config = {
  target: 'node',
  externals: [nodeExternals()],
  entry: {
    'src/index': './src/index.js',
    'test/index': './test/index.js'
  },
  output: {
    path: __dirname,
    filename: '[name].bundle.js',
    libraryTarget: 'commonjs2'
  },
  module: {
    rules: [{
      test: /\.js$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['env', {
              'targets': {
                'node': 'current'
              }
            }]
          ]
        }
      }
    }]
  }
}

export default [config]
Tyler Liu
  • 19,552
  • 11
  • 100
  • 84
  • 1
    Can you please explain - `for node.js, it doesn't make much sense to bundle node_modules/` - is this because it's running on the server and we don't need to worry about bundling our code to reduce the number of requests? Learning here ... thanks. – Ryan-Neal Mes Apr 27 '17 at 18:16
  • 1
    @Ryan-NealMes `it's running on the server and we don't need to worry about bundling our code to reduce the number of requests` is correct. Another reason is there is duplicate code if some libraries exist both in 'node_modules/' and in your bundle. – Tyler Liu Apr 28 '17 at 01:35
  • How do you use this generated server-side bundle? – 1252748 Aug 18 '17 at 16:27
  • @1252748 I am mainly talking about server side libraries here. Most likely I will publish it to npmjs.org. Then every one can install and use it just like other node.js libraries. If what you have is an app instead of a library, you can always extract some code and make it a library just to reuse code. – Tyler Liu Aug 19 '17 at 01:12
  • Ah, I was using the `target: 'node'` setting so I could bundle up an express server, and dockerize both front and back end bundles for production use. Would you say that's a typical use of this config option? – 1252748 Aug 19 '17 at 01:16
  • Is there a recommended way to watch the server script and its dependencies and restart when required? – Henry Nov 20 '17 at 01:40
1

Here is the webpack configuration I have used to in my Nodejs application when I wanted it to read JSX which as you know, Node cannot do.

const path = require('path');

module.exports = {
  // inform webpack that I am building a bundle for nodejs rather than for the
  // browser
  target: 'node',

  // tell webpack the root file of my server application
  entry: './src/index.js',

  // tells webpack where to put the output file generated
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'build')
  },

  // tells webpack to run babel on every file it runs through
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          presets: [
            'react',
            'stage-0',
            ['env', { targets: { browsers: ['last 2 versions'] } }]
          ]
        }
      }
    ]
  }
};

After you implement this though, don't forget to head over to your package.json file and include this script:

{
  "name": "react-ssr",
  "version": "1.0.0",
  "description": "Server side rendering project",
  "main": "index.js",
  "scripts": {
    "dev:build:server": "webpack --config webpack.server.js"
  },
Daniel
  • 14,004
  • 16
  • 96
  • 156