Bundle Size issues caused by Webpack failing to tree-shake
See original GitHub issueBug report
We noticed bundle size issues in our Next.js application. More specifically we noticed that basically all of the code served on all routes, even though most of it was not needed.
After hours of debugging I finally managed to find the line of code responsible for this behaviour…
Describe the bug
Webpack is failing to tree-shake Components with static properties.
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
- Clone https://github.com/MrAvantiC/next-tree-shaking-issues
- Run
npm run build && npm start
- Visit localhost:3000
- Open network tab and see contents of
index.js
- You will find the following Code:
var O = function(t) {
p(e, t);
var n = _(e);
function e() {
var t;
i(this, e);
for (var r = arguments.length, o = new Array(r), c = 0; c < r; c++)
o[c] = arguments[c];
return v(l(t = n.call.apply(n, [this].concat(o))), "withStaticFunction", (function() {
console.log("withStaticFunction")
}
)),
t
}
return a(e, [{
key: "render",
value: function() {
return S("h1", null, "TestWithStatic")
}
}]),
e
}(r.Component);
v(O, "defaultProps", {
foo: "bar"
});
- Stop Server, open
components/TestWithStatic/index.js
and delete line 4static defaultProps = { foo: 'bar' }
- Repeat steps 2 to 4 and you will see, that the unused Component has now been correctly tree shaken.
Expected behavior
Unused Components should always be excluded from the bundle
System information
- Version of Next.js: 9.3.6
Additional context
I found a couple of related issues:
- Another library with the same issue: https://github.com/alex996/react-css-spinners/issues/1
- Weback itself: https://github.com/webpack/webpack/issues/8308
Webpack closed the issue saying:
Does this mean webpack has no intention of changing this behavior in the future?
webpack is not doing the Dead-Code-Elimination. It’s done by uglify-js2 (webpack 4) or terser (webpack 5). If you want this behavior changed, that’s where to look.
Anyway, I’m going to fix this for our project, but maybe Next.js should guide users here and fix this issue by default, however the fix may look like…
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
Not super knowledgable about compilation methods, but it appears that React elements are being assigned (not by an identifiable name), but are just never utilized. When using a
static
reference, it appears to transform the code differently, but again still not utilized.For example, look at how many times
createElement
is assigned to a variable:With sideEffects (4):
Without sideEffects/direct imports (2):
This isn’t a problem with Next, nor does it stem from class properties, but the problem comes from this file. Webpack doesn’t tree shake this file properly because it’s not sure if it has side effects or not. You can mark it as side effect free by including this in your
package.json
file:However, this may not be the case for all your files, and specifying which does or doesn’t have side effects may be cumbersome, so alternatively you may want to restructure your imports to be direct:
Results
Not marked as side-effect free:
Marked as side-effect free:
Direct import: