webpack / webpack

A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.
https://webpack.js.org
MIT License
64.76k stars 8.83k forks source link

Should I minify node_modules or should I use the minified version provided for deploy on client? #615

Closed bitplanets closed 8 years ago

bitplanets commented 9 years ago

I recently moved to webpack from require.js and some node_module have .min files built in. When I use a file from node_module I just do require('my-module') and it loads it right away without any config. But this will load the development version or a bigger version.

For example react is loaded require('react/addons') but this is not the minified version.

My question is:

For now, I'm changing the aliases of webpack to load the minified version when building the app:

myConfig.resolve.alias.phaserUnFixed = "nodeModules/phaser/build/custom/phaser-no-physics.min.js";
myConfig.resolve.alias.react = "nodeModules/react/dist/react-with-addons.min.js";
myConfig.resolve.alias.lodash = "nodeModules/lodash/dist/lodash.compat.min.js";
myConfig.resolve.alias.moment = "nodeModules/moment/min/moment.min.js";

But this is not a good approach either... Can you think of anything better?

sokra commented 9 years ago

I use the non-minimized versions and let webpack minimize them for production (--optimize-minimize or the UglifyJsPlugin). Some libs have special debugging features, i. e. React tests process.env.NODE_ENV !== "production". You can define this with the DefinePlugin and it'll be removed from the bundle ( new DefinePlugin({ "process.env": { NODE_ENV: JSON.stringify("production") } })).

So this is recommended.


But you could also do this:

myConfig.resolve.alias.phaserUnFixed = "nodeModules/phaser/build/custom/phaser-no-physics";
myConfig.resolve.alias.react = "nodeModules/react/dist/react-with-addons";
myConfig.resolve.alias.lodash = "nodeModules/lodash/dist/lodash.compat";
myConfig.resolve.alias.moment = "nodeModules/moment/min/moment";

if(production)
  myConfig.resolve.extensions.splice(1, 0, ".min.js");
bitplanets commented 9 years ago

Well with react the difference is just 22KB in my project (less if I use their min file). But in phaser for example the difference is huge:

Would be nice to have a production setting that will automatically load the min file or something similar.

Why do you use JSON.stringify("production") instead of "production"?

ColCh commented 9 years ago

My approach : use 2 configs - one for prod and one for dev. In dev config leave as it was. In prod config define aliases from modules to their min versions: e.x. alias react -> react/dist/react.min.js.

Advice 1: also you can add these minifed versions to module.noParse to skip parsing on 'em and speed up build Advice 2: It's preferred not to use min version, because UglifyJS can freeze on them (Yes. No errors. Just hangs!). I faced this trouble with using preminified versions of Kendo UI and CKEDITOR

TheSisb commented 9 years ago

@bitplanets - there's no reason why the non-min file + minification in webpack won't be the same as the provided min file from the developer. UNLESS you aren't providing the "mangle" parameter to uglifyJS (not passed by default I don't think).

It's best to use non-min files and compress them from within webpack as @sokra recommended.

I don't recommend managing two separate configs - one is often ignored (usually production, which is bad) and often results in duplication of config code.

bitplanets commented 9 years ago

@TheSisb

there's no reason why the non-min file + minification in webpack won't be the same as the provided min file from the developer. UNLESS you aren't providing the "mangle" parameter to uglifyJS (not passed by default I don't think).

One reason is +1.5MB in my js. I don't use mangle.

It's best to use non-min files and compress them from within webpack as @sokra recommended.

Can you live with extra 1.5MB?

I don't recommend managing two separate configs - one is often ignored (usually production, which is bad)

How is ignored? Or what exactly is ignored?

and often results in duplication of config code.

Is not really duplication of code. Is like a webpack module which does 2 different things: on client does X on server does Y.

bitplanets commented 9 years ago

@ColCh I see good points in there. For now everything worked perfectly with min+uglify.

sokra commented 9 years ago

Can you live with extra 1.5MB?

If you are talking about react, there must be something wrong with your configuration. If you build react from source with webpack it's even smaller than the original build.

// webpack.config.js
var webpack = require("webpack");
module.exports = {
    output: {
        libraryTarget: "umd",
        library: "React"
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin(),
        new webpack.BannerPlugin([
            "/**",
            " * React v0.12.1",
            " *",
            " * Copyright 2013-2014, Facebook, Inc.",
            " * All rights reserved.",
            " *",
            " * This source code is licensed under the BSD-style license found in the",
            " * LICENSE file in the root directory of this source tree. An additional grant",
            " * of patent rights can be found in the PATENTS file in the same directory.",
            " *",
            " */"
        ].join("\n"), { raw: true }),
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify("production")
            }
        })
    ]
}
$ npm install webpack react
react@0.12.1
webpack@1.4.13
$ webpack react react.webpack.min.js
$ webpack react/addons react-with-addons.webpack.min.js
140304 react-with-addons.min.js
119658 react-with-addons.webpack.min.js
130289 react.min.js
111012 react.webpack.min.js

I don't recommend managing two separate configs - one is often ignored (usually production, which is bad) and often results in duplication of config code.

// webpack.production.config.js
var config = require("./webpack.config.js");
config.plugins.push(...);
// ...
module.exports = config;
bitplanets commented 9 years ago

@sokra I'm talking about phaser, no react. Also my lib is included within, but the difference is 1.5MB

sokra commented 9 years ago
741233 phaser.min.js
783044 phaser.webpack.min.js
bitplanets commented 9 years ago

@sokra I will try again to compile just the phaser lib instead... Might be something else that is messing it.

TheSisb commented 9 years ago

@sokra Brilliant! Thanks :)

re:

// webpack.production.config.js
var config = require("./webpack.config.js");
luckylooke commented 9 years ago

Webpack have some problem with Phaser library on ubuntu see: https://github.com/the-simian/slush-phaser-webpack/issues/2 Seems to be related to this issue, but I could not help with this thread either.

srcspider commented 9 years ago

Why do you use JSON.stringify("production") instead of "production"?

"production" produces the value production JSON.stringify("production") produces the value "production"

Essentially it's converting the string to evaluate-able piece of javascript coce.

It's probably much clearer and shorter to just write '"production"'

bebraw commented 8 years ago

@bitplanets Safe to close?

alltom commented 8 years ago

UglifyJsPlugin used to make my source code several megabytes bigger too, but then I read the docs and found that it generates source maps by default. If I invoke it with that option disabled, the minified version is as small as I expected:

new webpack.optimize.UglifyJsPlugin({sourceMap: false})
srcspider commented 8 years ago

@alltom just extract the source maps to a separate file and it's fix'ed with out any negative consequences.

wayofthefuture commented 7 years ago

Will Webpack automatically include requires from node modules for minification? Or do I have to explicitly set to minify the node module references?