webpack按需加载配置和babel编译
当我们在开发一个开源库的时候,怎么样也能让使用者能够按需加载呢?直接提供给对方打包后的文件或者 ES6 原始文件就可以了吗?答案是不行的
平时我们经常使用的一些开源库可以通过按需加载来减小引入资源的大小,这种一般是使用到了 webpack 的tree-shaking
,时间久了大家也就自然而然的以为这是 webpack 本身就有的功能,那么,当我们在开发一个开源库的时候,怎么样也能让使用者能够按需加载呢?直接提供给对方打包后的文件或者 ES6 原始文件就可以了吗?答案是不行的,我们需要搞清楚 webpack 怎么样才能实现tree-shaking
。这里我不在解释什么是tree-shaking
,我只来说明怎么样才能让我们开发出来的库文件可以使用tree-shaking
# 1.使用 tree-shaking 的前提条件
webpack 文档 (opens new window)写的很清楚,在 tree-shaking 章节下面的结论那里列了 4 个条件。
- 使用 ES2015 的模块语法。
- 确保没有编译器将 ES2015 模块语法转为 CommonJS 的模块语法。
- 在项目的 package.json 文件中,添加 "sideEffects" 属性。
- 使用 mode 为 "production" 的配置项以启用更多优化项,包括压缩代码与 tree shaking.
# 2.项目中如何配置
文档写的很清楚,前 3 个条件是针对我们库文件的条件,最后一个是在使用的时候需要注意的点,接下来我将分条目进行说明。
# 使用 ES2015 的模块语法
webpack 的tree-shaking
依赖于 ES2015 的模块语法,即 ES6 的import
和export
语法,所以我们的库文件在提供出去的时候需要保持 ES6 的模块语法,不能转译为 CommonJS 的语法,这点需要注意,我们在发布我们的库文件到 NPM 上的时候,一般会提供一个 ES5 文件供浏览器中直接引入,另外再提供一份 ES6 模块文件供开发中使用,这里在babel
中进行配置即可。
目前 babel 版本为 7,使用的配置文件为babel.config.js
,我们可以通过环境变量NODE_ENV
来区分不同的环境,通过设置preset
的modules
为 false 来保留 ES6 模块语法,可参考babel-preset-env (opens new window),具体配置如下:
presets: [
[
'@babel/preset-env',
{
modules: false, // babel编译的时候保留 es module方式
targets: {
browsers: ['> 1%', 'last 2 versions', 'not ie <= 8']
}
}
]
]
2
3
4
5
6
7
8
9
10
11
第二条和第一条基本相同,我们开发的时候保留 ES6 模块即可。
# 在项目的 package.json 文件中,添加 "sideEffects" 属性。
sideEffects 即副作用影响,即在 webpack 打包的时候告诉 webpack 哪些是没有副作用的可以直接去掉,具体的说明可以看这篇文章 (opens new window),通常情况下我们可以直接设置sideEffects:false
来表明文件都是没有副作用的可以直接tree-shaking
, 但是这里需要注意的是,在开发的过程中,会把一些 import 的但是没有使用的文件删除掉,例如一些单独导入的 less,css,scss 文件没有打包进去,因此在配置的时候需要额外的注意,我们可以配置哪些文件有副作用不用tree-shaking
,配置如下:
"sideEffects": [
"*.vue",
"*.css",
"*.scss",
"*.sass",
"*.less"
]
2
3
4
5
6
7
其他的一些说明。
在我们提供的npm库文件的时候,一般会在package.json
中提供一个main
字段来表明包的入口,其实还有一个module
字段也可以设置包的入口,这些的设置也有助于tree-shaking
的使用,具体可以看这篇博文 (opens new window)
# 4. 使用tree-shaking
使用tree-shaking
就相对比较简单了,如果我们的NPM包支持tree-shaking了,那么我们在编译的时候添加mode: 'production'
,并启用压缩即可,webpack会自动对我们引入的NPM包进行tree-shaking
处理。