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

webpack 4 tree-shaking sideEffects: false removes styles for single-file vue components in production builds #1435

Closed
sjones6 opened this issue Nov 21, 2018 · 7 comments · Fixed by #1485
Labels

Comments

@sjones6
Copy link

sjones6 commented Nov 21, 2018

Version

15.4.0

Reproduction link

https://github.com/WireWheel/style-tree-shaking-bug

Steps to reproduce

Pull down the repo.

  1. Install deps: npx lerna bootstrap --hoist
  2. Run npm run build

Take a look in dist/css/index.[hash].css and notice that the styles in packages/one/components/HelloWorld.vue are not in the extracted css file.

  1. Set sideEffects: true in packages/one/package.json
  2. Rebuild with npm run build

Styles are now included in the dist/css/index.[hash].css.

What is expected?

styles are not removed for components included in the bundle.

What is actually happening?

styles are omitted from the bundled css.


The solution here could be to say that you cannot use sideEffects: false as a valid setting for any package that includes single-file Vue components. If so, it'd might be sufficient to document that. It'd be great if tree shaking could still be used in this setup without losing the styles.

The key components here are:

  1. webpack 4 tree-shaking
  2. a mono-repo (or at least a single-file Vue component in a separate package) with sideEffects: false in the package.json

I'm opening this against vue-loader since it seems appropriate for the vue-ecosystem—but things at play are webpack, vue-loader, css-loader, etc.

@posva
Copy link
Member

posva commented Nov 21, 2018

Check webpack/webpack#6741
I think we could document this for library authors. Importing css is a side effect

@sjones6
Copy link
Author

sjones6 commented Nov 26, 2018

@posva : Thanks for the reference.

For clarity, it would impact both library authors and monorepo projects. Updating the docs for vue-loader would probably be sufficient to close this out.

@gombosg
Copy link

gombosg commented Nov 30, 2018

Yes, it doesn't just affect library authors. We have a monorepo for our app and "sideEffects": false was present in package.json.
When we compiled in Webpack with mode: 'production', CSS files @imported from Vue single-file components were dropped from the final CSS file output which caused page rendering issues. (But it compiled without errors or warnings!)

Removing "sideEffects": false solved the issue.

So this should definitely be documented somewhere e.g. here.

@gombosg
Copy link

gombosg commented Mar 5, 2019

An important update. As of now, I need to use

  "sideEffects": [
    "*.css",
    "*.vue"
  ]

in package.json, in order to use Webpack tree shaking in Production mode. Just CSS is not enough.

You can try it by running Webpack in Development mode, with usedExports: true, then search for unused harmony in the output. It marks CSS files as unused exports, discarding them in Production.

@thelonecabbage
Copy link

So weirdly, this works. Essentially it's an instruction to the vue-loader to import and use the style from the same file (recursively). The resulting value of style is {}, but it tricks webpack into thinking the style in this file is not a side-effect.

-- file: Palette.vue ---

<script>
import style from './Palette.vue?vue&type=style&index=0&module=true&lang=stylus&'

export default {
   style,
   ...
}
</script>
<style scoped lang="stylus">
...
</style>

I'm NOT suggesting this as a solution, but would it be possible to append a similar import to the front of the script section automatically in the vue-loader, thereby making the style mandatory .

@maxKimoby
Copy link

@gombosg 's solution is what made my day. This is not documented anywhere. Our build was not tree shaking until we added the *.vue element in the sideEffects array.

@nskazki
Copy link

nskazki commented Jun 26, 2021

I have my own set of UI components and a file re-exporting those components, so I can spare a few keystrokes, i.e.

// ui-components/index.js
export { default as ComponentA } from './ComponentA.vue
export { default as ComponentB } from './ComponentB.vue
...
// my-view.js
import { ComponentA } from '../ui'
...

And I struggled to exclude unused Vue modules without excluding the styles of the used ones until I came across @thelonecabbage's answer (#1435 (comment)) and I'm sincerely thankful for giving me an idea of how the tree-shaking can finally be fixed in my project:

{
  module: { 
    rules: [{
      test: /\.vue$/,
      sideEffects: false
    }, {
      test: /\.vue$/,
      resourceQuery: /type=style/,
      sideEffects: true
    }]
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants