-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Production build tree shaking not working #9717
Comments
Tree-shaking lodash depends on the build process. In this case, you need to import it slightly differently:
This is the most consistent way I've found to ensure tree-shaking for lodash no matter the build process. I'm not sure what |
@philipjfulcher Deep imports are not the same thing as tree shaking. The babel plugin you're most likely referring to is the one that rewrites the imports to deep imports, but that is not the same as tree shaking, and it is not present in create react app. Lodash is also not the only thing a user would want optimized so a plugin that rewrites Lodash imports doesn't really solve the issue with tree shaking here. It is a very complicated thing, and I was confused when learning about this, but quoting the webpack docs:
In my opinion, this is pretty unambiguous that unused exports should optimize things without resorting to writing deep imports. One thing on Nx's side that would be useful to look into, which may be related to this issue:
|
https://webpack.js.org/configuration/optimization/#optimizationsideeffects By logging out the webpack configs that nx is using, I see it has Additionally, Nx has my tsconfig.json set to I fully expect both of these issues to prevent tree shaking. After I fixed both of these issues, I can confirm Nx properly tree shakes 👍 . All I did was:
(see https://nx.dev/guides/customize-webpack) and in In turn these changes break Jest, to fix this I added jest.preset.js:
babel.config.json:
And now jest works again After making these changes and switching branches
After |
A full solution that worked for me.
{
"targets": {
"build": {
"options": {
"webpackConfig": "apps/<app>/custom-webpack.config.js"
}
}
}
}
const { merge } = require('webpack-merge')
const getWebpackConfig = require('@nrwl/react/plugins/webpack')
module.exports = (config, _context) => {
return merge(getWebpackConfig(config), {
optimization: {
sideEffects: true,
},
})
}
{
"sideEffects": false
} If your app has side effects, for example, global styles, you need to specify an array of effectful files in the {
"sideEffects": ["apps/<app>/src/styles/index.css"]
} I didn't have problems with Jest or |
I've encountered the same problem with a plain react application using the @nrwl/react generator. I've set up a reproducible sample project here: https://github.com/rudfoss/nx-bundling-issue It is a clean nx workspace project with a vanilla generated react application (using SWC compiler) so if it should work I would expect it to here. The problem occurs when trying to import from react-icons which does not tree-shake correctly. I tried the fix suggested by @vlad-khitev-axon above, but it does not seem to work. Any tips on how to resolve this? |
I've moved from swc to babel and that seems to have resolved the tree shaking problem. Still seems strange that it does not work with swc, but at least we can bundle it now :) |
Actually you only need to add the Also thanks a lot for the response, it helped me a lot! |
That was not my experience. In my original issue report, I found that Nx is passing |
Got it! In my case simply adding to package.json made me get the desired result, I did as you said and I got no difference from just adding it to the package.json. I think it's because webpack already takes the package.json sideeffect into consideration https://webpack.js.org/guides/tree-shaking/ But either way this was a great find! Thanks a lot |
Yeah, depending on the Nx generator that created your webpack config, or your version of Nx, you may or may not be experiencing the issue with it being turned off in webpack. Separately, you may find you also need package.json changes, it depends :) |
@LeonardoGobbiLopez Thank you! 🎉 the webpack |
Tree shaking does not work for me on a freshly installed nx workspace using Webpack and Babel. Reproduce issue
Import a library which exports a barrel file. I'll use import { getDate } from 'date-fns';
console.log(getDate); // use it somewhere
export function App() {
return null;
} Now let's look at both the development and production builds in Development build
// EXTERNAL MODULE: ../../node_modules/date-fns/index.js
var date_fns = __webpack_require__(3753); Production build
You should see something like: The fixI did some extensive digging and managed to solve the issue by extending/overriding the default webpack config: // Fix 1: resolves tree-shaking issue
// The default in NX is [ 'browser', 'main', 'module' ]. Thus, 'main' had preference over 'module' when Webpack reads the `package.json` files, which is not what we want. Module should become before main - the order matters!
// See https://webpack.js.org/configuration/resolve/#resolvemainfields
config.resolve.mainFields = ['browser', 'module', 'main'];
// Fix 2: resolves minification issue by adding Terser. Terser is also capable of eliminating dead code.
// TerserJS is the Webpack 5 default minifier but we have to specify it explicitly as soon as we include more minifiers
config.optimization.minimizer.unshift(new TerserJSPlugin()); You will now see that the module is concatenated and only the required date functions are imported: Full code of const { composePlugins, withNx } = require('@nrwl/webpack');
const { withReact } = require('@nrwl/react');
const TerserJSPlugin = require('terser-webpack-plugin');
module.exports = composePlugins(withNx(), withReact(), (config) => {
config.resolve.mainFields = ['browser', 'module', 'main'];
config.optimization.minimizer.unshift(new TerserJSPlugin());
return config;
}); After altering the Webpack configuration, the bundle size went from Tree shaking lodashTree shaking lodash by using named imports (i.e.
Using ViteI can confirm that tree shaking and minification does work out-of-the-box on a fresh workspace using Vite + SCW. For some this might be the way to go. In my case, however, I need Webpack as I want to experiment with Module Federation. |
Thanks @Jasonkoolman - that did the trick for me! note to anyone using merge(config, { resolve: { mainFields: ['browser', 'module', 'main'] } }) will yield config.resolve.mainFields === ['browser', 'main', 'module', 'browser', 'module', 'main']; |
I've found solution for angular apps: |
This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context. |
Tree shaking does not work. I created a React app with both Nx and
create-react-app
, and imported a single lodash function.Current Behavior
Nx bundle:
Expected Behavior
Create react app bundle:
Steps to Reproduce
Environment
The text was updated successfully, but these errors were encountered: