Disable tree shaking in Webpack 4

2020-08-23 04:51发布

问题:

Is there a config option to disable unused module detection in Webpack 4?

We recently switched from lodash to lodash-es to support tree shaking. It works great and the bundles are much smaller, but now our build takes about twice as long (up from 3 minutes to 6 minutes).

Would be great to disable it on dev to speed up the build, since bundle size doesn't matter there.

I found this undocumented config option but I'm not sure how it would apply https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsDefaulter.js#L207. Obviously UglifyJS is not running in dev so i'm assuming all of the slowdown comes from Webpack doing the work to mark which modules are unused.

I was thinking you could do something like aliasing lodash-es to lodash only on dev, but that's super hacky, and anyway Lodash doesn't work with the import * as _ syntax that lodash-es requires for tree shaking

I'm assuming this is the plugin that does the work of marking imports as unused, but since it's enabled by default I don't know how to disable it or remove it from the plugins array https://github.com/webpack/webpack/blob/next/lib/optimize/SideEffectsFlagPlugin.js#L1

It seems strange you can't just set treeShaking: false or something in the config. https://webpack.js.org/guides/tree-shaking/ doesn't mention anything.

We are already setting mode to development or production based on the build environment, but we see these slower build times even on development. this would suggest that mode: development does not disable the unused module detection.

回答1:

Well, I couldn't find anything in the docs, but this is a relatively inoffensive workaround:

Add

{
    test: () => !env.production,
    sideEffects: true,
},

To your module.rules array. That rule will match every file when running in dev mode, and no files when running in prod mode. When it matches a file, it tells Webpack (falsely) that the file has side effects, and so cannot be tree-shaken.

This brought our build times back from 6 minutes to 3 minutes on dev.

Hardly ideal but in the absence of a proper config option from Webpack this will have to do.

It also seems better than other alternatives, like enabling Babel CJS module transforms only in dev, since that could cause subtle bugs that only appear in production due to the differences in semantics/behaviour between mutable CJS modules and immutable ES modules.



回答2:

So, my other answer does help, but not by much. While it avoids tree shaking, this just causes the build to inline the full copy of lodash into every bundle. For a codebase like ours with 100s of entry points, this is still very inefficient. It made the build faster than 6 minutes, but no where near the original 3 minutes.

I the end I used externals to conditionally ignore Lodash imports entirely, only in dev. This can be done something like

    externals: {
        ...(isProduction ? {} : { 'lodash-es': '_' }),
    },

You would then need to write some logic to conditionally include a script tag for the full Lodash build only on dev into your head tag.

So this isn't really a generic answer to this question – more specific to our use case of Lodash and a very large codebase. For other codebases or dependencies, disabling tree shaking might be the right answer.



标签: webpack