Skip to content
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 isn't tree shaking buildable libraries #260

Open
gregveres opened this issue Jun 16, 2022 · 9 comments
Open

Production build isn't tree shaking buildable libraries #260

gregveres opened this issue Jun 16, 2022 · 9 comments
Labels
bug Something isn't working

Comments

@gregveres
Copy link
Contributor

Current Behavior

I have produced a reproduction repo. The repo contains one application and one library. In the library are two components: HelloWorld and GoodByeWorld. HelloWorld is used by app.vue but GoodByeWorld isn't used by anything in the application. As a result, I would have expected GoodByeWorld to be removed from the bundle by webpack's tree shaking.

The current behaviour is that the app.js created by the production build still contains GoodByeWorld.vue. Here is the image from Bundle Analyzer:
image

And when I bring app.js into the editor and search for GoodByeWorld, I find:

...
,_=[],j=n["a"].extend({name:"GoodByeWorld"})
...

This indicates that GoodByeWorld is indeed in the bundle.

Expected Behavior

I expect GoodByeWorld to be removed from the bundle because it isn't referenced anywhere.
I have been converting a fairly large project over to NX and when I was finished I realized that tree shaking wasn't happening and my bundles were much bigger and contained much different content than I had expected.

Steps to Reproduce

Here is a github reproduction:
https://github.com/gregveres/nx-plus-vue-tree-shaking

clone this repo, and then run the production build with:
nx build main --prod --mode="production"

This will launch bundle analyzer immediately. Just look at the app.js bundle (uncheck others).

Failure Logs

There are no failure logs

Environment

I am bulding a Vue 2 application

Plugin name and version: nx-plus/vue@14.0.0

06-16 18:22:37 11> nx report

 >  NX   Report complete - copy this into the issue template

   Node : 16.13.2
   OS   : win32 x64
   npm  : 8.1.2
   
   nx : 14.3.6
   @nrwl/angular : Not Found
   @nrwl/cypress : 14.3.6
   @nrwl/detox : Not Found
   @nrwl/devkit : 14.3.6
   @nrwl/eslint-plugin-nx : 14.3.6
   @nrwl/express : Not Found
   @nrwl/jest : 14.3.6
   @nrwl/js : Not Found
   @nrwl/linter : 14.3.6
   @nrwl/nest : Not Found
   @nrwl/next : Not Found
   @nrwl/node : Not Found
   @nrwl/nx-cloud : Not Found
   @nrwl/nx-plugin : Not Found
   @nrwl/react : Not Found
   @nrwl/react-native : Not Found
   @nrwl/schematics : Not Found
   @nrwl/storybook : Not Found
   @nrwl/web : Not Found
   @nrwl/workspace : 14.3.6
   typescript : 4.7.3
   ---------------------------------------
   Community plugins:
         @nx-plus/vue: 14.0.0
@gregveres gregveres added the bug Something isn't working label Jun 16, 2022
@gregveres
Copy link
Contributor Author

Is there a way to extract the configuration for webpack?

@gregveres
Copy link
Contributor Author

I figured out what is missing.
I had to add "sideEffects": false to all of my library's package.json files.
Once I did that webpack started to work as expected.
Here is the issue on the Nx main project site that pointed me in the right direction. Apparently this is a common issue. Webpack 5 is supposed to be better at doing the right thing automatically, but you can achieve it with webpack 4 with the use of the sideEffects: false entry.

I dropped over 200KB from my main app.js bundle size and 2MB from the total of my javascript files.

I am not sure if the plugin should be adding "sideEffects": false to the library's package.json file when it is created. I can see the argument that sideEffects: false might be promising something that might not be true for some libraries. But I always operate under the premiss that defaults should work for 90% of the use cases and I think that sideEffects: false definitely falls into that category.

@gregveres
Copy link
Contributor Author

This can also be changed from a bug to a feature request.

@gregveres
Copy link
Contributor Author

Unfortunately, I have figured out that every vue file that uses styles has a sideeffect and that is that the compiled JS file needs to be accompanied by the compiled .css file.
Once I switched all my libs to sideEffects: false and did the production build, I realized that none of the component style files were being loaded.

I am still searching for the solution that allows me to have tree shaking (because it makes a huge difference) and loading of the component style files.

@gregveres
Copy link
Contributor Author

I think I have found the proper solution as mentioned here..

For the libraries that contain vue files, I have changed sideEffects: false to sideEffects: ["*.vue"].
This tells webpack that vue files still have side effects and this causes webpack to properly include the .css files that correspond to the vue files.

I believe this new version of the sideEffect can be used for libs that don't have .vue files without problem. So, to amend my question above, should the libs have this sideEffect: ["*.vue"] by default?

@ZachJW34
Copy link
Owner

I've run into a very similar problem with nx + Angular in the past. Just to clarify, are you building the libs and then consuming them in your app or relying on Typescript aliases. From your repro it looks like the former, I'd be curious about tree-shaking when it comes to just relying on the aliases.

I think it makes sense to add the sideEffect to the generated packge.json for buildable libs if you're interested in contributing.

@gregveres
Copy link
Contributor Author

gregveres commented Jun 17, 2022 via email

@ZachJW34
Copy link
Owner

@gregveres as long as vue-cli is popular I plan on supporting it. I added the vite plugin cause it was fun to do

@hackmajoris
Copy link

I have the same problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants