What Does Webpack 4 Expect From A Package With sideEffects: false

后端 未结 2 936
执笔经年
执笔经年 2020-12-22 22:54

Webpack 4 has added a new feature: it now supports a sideEffects flag in the package.json of the modules it is bundling.

From Webpack 4: r

2条回答
  •  眼角桃花
    2020-12-22 23:15

    This sideEffects setting is very vague and is not described sufficiently in the docs. The docs are mostly like "there's a sideEffects flag for modules free of any side effects".

    The consensus is that "has no sideEffects" phrase can be decyphered as "doesn't talk to things external to the module at the top level".

    My current understanding is that this sideEffects flag is only for "re-exports", a "re-export" being:

    export { a } from './lib/a'
    export { b } from './lib/b'
    

    somewhere in /index.js (or any other file inside the ).

    If Webpack detects that the application only imports a from , and doesn't import b anywhere, then Webpack can simply drop the export { b } from './lib/b' line from /index.js resulting in not including './lib/b.js' file in the resulting bundle (which makes it smaller by the size of './lib/b.js' file).

    Now, if './lib/b.js' had some top-level lines of code doing some "side effects", i.e. if './lib/b.js' did something like:

    • window.jQuery = ...
    • if (!global.Set) global.Set = require('babel-polyfill').Set
    • new XmlHttpRequest().post('/analytics', data)

    then './lib/b.js' would be said to have "side effects" because its top-level code (which gets executed upon import './lib/b') affects something outside the scope of the './lib/b.js' file.

    At the same time, as long as './lib/b.js' top-level code doesn't reach outside that *.js file then it's not having any "side effects":

    let a = 1
    a = a + 1 + computeSomeValue()
    export default a
    export const b = a + 1
    export const c = b + 1
    

    these are all not "side effects".

    And there's a final gotcha: if an npm package has any *.css files that a user can import then these *.css files are all "side effects", because:

    import 'npm-package/style.css'
    

    has no variable assigned to this import which effectively means "this imported module is not used anywhere in the application" for Webpack. And so Webpack simply discards the 'npm-package/style.css' file from the bundle as part of the "tree-shaking" process if the npm-package has sideEffects: false flag. So, instead of writing sideEffects: false always write "sideEffects": ["*.css"]. Even if your npm package doesn't export any CSS files it might do so in some future and this will guard against the aforementioned "CSS file not included" bug.

提交回复
热议问题