webpack tree shaking 踩坑

首先描述一下问题场景

一个项目中webpack升级到4.x.x版本后在development模式下项目是完全正常工作的,但是在production模式下没有把antd的css文件打包进去。
项目中webpack和antd的版本如下:

antd:3.4.5
webpack:4.27.0

项目中我们是这样引入antd的样式文件的:

import 'antd/dist/antd.css';

经过一番查找排查我们发现如果我们在项目中这样引入样式文件项目无论在webpack的develepment或者production模式下都能够正常运行:

1. require('antd/dist/antd.css');

2. @import '~antd/dist/antd.css';

3. 使用babel-plugin-import按需加载

4. import 'antd/lib/style/index.css';
   import 'antd/lib/style/components.css';

最终我们发现原来这一切都是webpack tree shaking惹的祸,所谓tree shaking可以这样解释:

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)

而webpack4正式版本之后扩展这个检测能力,在production模式下会检测那些未引用的代码,然后删除。同时这个tree shaking依赖于 ES2015 模块系统中的静态结构特性,例如 importexport。这样就很好的解释了为什么1、2、3为什么能够正常工作,因为他们都没有使用import来导入样式文件(3内部也是使用require)。而4这种情况是因为我们可以在package.json的sideEffects指定哪些文件是有副作用的,这样webpack在打包的时候就不会将他们删除掉了(关于webpack tree shaking的详细内容可以看这里)。我们再去antd的package.json中看一下发现它的sideEffects是这样写的:

 "sideEffects": [
    "es/**/style/*",
    "lib/**/style/*"
  ]

其中并没有标明dist目录下的文件是有副作用的,所以4也就很好解释了。

建议:

  1. 在项目中引入antd的时候尽量使用babel-plugin-import按需加载(最新的antd版本中已经指明dist目录下的文件是有副作用的)
  2. 使用webpack4以后的版本的时候对于有副作用的文件的引入如果在代码中没有引用那么需要在package.json的sideEffects中指明文件路径。

相关issue: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/275

你可能感兴趣的:(总结)