christianalfoni / webpack-express-boilerplate

A boilerplate for running a Webpack workflow in Node express
MIT License
1.39k stars 291 forks source link

Why are Webpack-related packages required unconditionally in server.js? #66

Open simevidas opened 7 years ago

simevidas commented 7 years ago

I apologize if this is a stupid question. I’m just about to start using Webpack for my Express web app.

In server.js, I see that webpack, webpack-dev-middleware, and webpack-hot-middleware are required at the top of the file, unconditionally.

const webpack = require('webpack');
const webpackMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

Shouldn’t these statements be inside the if (isDeveloping) branch? Otherwise, Webpack runs on the actual web server in production, if I understand correctly.

kbariotis commented 7 years ago

@simevidas Nope, that's not a stupid question at all. :)

The requirement of these packages doesn't mean that are going to run. The actual invocation happens bellow at lines #15, #16 and still those lines aren't causing webpack to run. Later below, the middleware variable is being passed as a middleware (l. #29) to express.js. This means that Webpack will run once a request comes in. This happens only in development, obviously.

You could add another bootstrap file for production if you like where webpack wont being required.

simevidas commented 7 years ago

Hm, if I understand correctly, require executes the module (i.e. the module’s code is parsed and compiled).

Example 1: foo is always parsed/compiled but only used in development:

let foo = require('foo');

if (development) {
  foo();
} 

Example 2: foo is only parsed, compiled and used in in development:

if (development) {
  let foo = require('foo');
  foo();
} 

I’m not sure why Webpack-related modules should be parsed and compiled in production. It just wastes server time and memory. (Correct me if I’m wrong.)

For comparison, this is my own setup and it works fine for HMR:

if (process.env.NODE_ENV === 'development') {
    let webpack = require('webpack');
    let config = require('./webpack.config');
    let compiler = webpack(config);

    app.use(require('webpack-dev-middleware')(compiler));
    app.use(require('webpack-hot-middleware')(compiler));
}
kbariotis commented 7 years ago

Indeed they are useless since they are never going to be used in production.

It justs wastes server time and memory.

Well yes but it's only loading the source code, which is really negligible. Actually server processing and usage waste happens when you actually tell webpack to do something.

Like I said, I would separate the server.js file into two. One that will use webpack and one that would not. I would argue that you should keep your requires in one single location, on the top of each file, for consistency and to avoid hidden circular references.

But either way, your code works just fine! :)

simevidas commented 7 years ago

I got curious so I run a test on my code - I’ve measured the time and memoryUsage before/after loading the 3 Webpack modules that are used for HMR:

if (process.env.NODE_ENV === 'development') {

    console.log(`Memory before: ${JSON.stringify(process.memoryUsage())}`);
    console.time('webpack');
    let webpack = require('webpack');
    let webpackDevMiddleware = require('webpack-dev-middleware');
    let webpackHotMiddleware = require('webpack-hot-middleware');
    console.timeEnd('webpack');
    console.log(`Memory after: ${JSON.stringify(process.memoryUsage())}`);

    let config = require('./webpack.config');
    let compiler = webpack(config);

    app.use(webpackDevMiddleware(compiler));
    app.use(webpackHotMiddleware(compiler));
}

The results are consistent on my machine. Here is one result:

Memory before: {"rss":28860416,"heapTotal":17862656,"heapUsed":9213872}
webpack: 749.479ms
Memory after: {"rss":44367872,"heapTotal":33591296,"heapUsed":21152024}

It looks like the Webpack modules take up ~16 MB, in addition to slowing down server boot (my app is not ready for deployment, so I can’t test on my actual web server yet).

I recommend optimizing the boilerplate, so that server resources aren’t wasted. This seems like a good idea for the default setup.

kbariotis commented 7 years ago

I would love to throw a PR. @christianalfoni what do you think?