Webpack 4.0发布了!!!
前端界最流行的模块管理库webpack又更新了一个大版本!!!
让我们看看这次带来了什么新特性吧!大量的性能提升,零配置,健全的默认设置。
webpack 4: 零配置
过去我们在使用webpack都需要提供一个配置文件,在大项目中可能觉得没什么,但在小项目中就会觉得很繁琐。于是,webpack团队在此次更新中解决了这个问题:webpack 4 doesn't need a configuration file by default!
让我们动手试试吧!
新建一个目录webpack-4-quickstart,然后安装webpack
mkdir webpack-4-quickstart && cd $_
npm init -y
npm i webpack webpack-cli --save-dev
webpack4需要安装webpack-cli
编辑package.json,添加一个build
命令
"scripts": {
"build": "webpack"
}
运行npm run build
,看看发生了什么?
WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.
ERROR in Entry module not found: Error: Can't resolve './src' in '~/webpack-4-quickstart'
噢!webpack4 会尝试在./src
中寻找入口文件,以前我们需要在webpack.config.js中定义entry,而在webpack4中它会默认定义./src/index.js为入口文件。
既然入口文件有默认值了,那output是什么呢?答案是./dist/main.js
留意刚才的错误提示中,还有一个WARNING,这又是webpack4的一个新特性。不着急,马上给你解释!
webpack 4: 开发与生产模式
以前我们使用webpack,通常需要定义两个配置文件,一个用于development环境,一个用于生产环境。
- development中,我们用于通常要配置webpack-dev-server和一些杂七杂八的设置
- production中,则需要配置UglifyJSPlugin, sourcemaps等
所以有了前面我们看到的那个大写的WARNING!!
打开package.json
,修改一下scripts
:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
再运行一次npm run build
,我们可以发现这次的./dist/main.js
比之前明显体积变小了有木有!
Production mode做了些什么事情呢?主要有minification, scope hoisting, tree-shaking等等。对应的Development mode则主要是优化编译速度,输出一个没有压缩的文件。
简单讲完这零配置和打包模式的新特性,我们接下来了解一下在实际运用中的一些新特性吧!
webpack 4:使用Babel转换ES6语法
虽然ES6标准已经出来挺长一段时间了,但是许多浏览器还是不能完全支持新的语法及API。于是我们要想办法将ES6让那些老旧的浏览器支持。webpack并不会替我们完成这个工作,但是它有各种loaders可用于转化我们的代码。
babel-loader就是用于将ES6或更高版本标准的JS转换成ES5的loader。
如何使用它,我们需要添加几个依赖包:babel-core
,babel-loader
,babel-preset-env
npm i babel-core babel-loader babel-preset-env --save-dev
然后在根目录新建一个.babelrc
来指定Babel的配置:
{
"presets": ["env"]
}
你可能会提出疑问了,不是说webpack4不需要配置文件了吗?
科科,webpack4 零配置只是说了不用你定义entry
和output
而已啦~
目前来说,你要用loaders还是需要创建配置文件的。至于未来会不会提供一些公用的loaders这个不好说,我们还是乖乖地新建一个webpack.config.js
吧~
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
}
接下来你可以尝试在./src/index.js
中写一些ES6了,运行npm run build
然后看看转换后的代码。
到这里有些倔强的童鞋要举手发言了,劳资就是不想用config.js不行吗?可以!满足你!我们可以用--module-bind
,不过这其实不是webpack4的特性,在webpack3的时候就有了。怎么用呢?
编辑package.json
:
"scripts": {
"dev": "webpack --mode development --module-bind js=babel-loader",
"build": "webpack --mode production --module-bind js=babel-loader"
}
满意了吧?反正我个人不太喜欢这种fat scripts
的做法。
总结一下更新的内容
- Environment
- 不再支持node.js v4
- Syntax
- import()总是返回一个命名空间的对象。CommonJS模块被封装到默认导出中
先写到这里吧,后面有时间再分享一下webpack4带来的其他新东西~
=================================================
更新2018-03-07
CommonsChunkPlugin
webpack4 去掉了CommonsChunkPlugin(RIP CommonsChunkPlugin),取而代之为optimization.splitChunks
和
optimization.runtimeChunk
这两个配置。下面我们来看看它是如何工作的。
webpack4默认为大部分用户提供了不错的配置。需要注意的是,这些默认配置只会异步请求的模块进行提取拆分,如果要对entry进行拆分的话,可以用optimization.splitChunks.chunks: "all"
。
webpack默认会按以下规则进行拆分提取:
- 新模块多处引用或者是来自
node_modules
的包 - 新模块的大小(压缩前)超过30KB
- 并发请求数低于或等于5
- 初始页面加载的并发请求数低于或等于3
配置
- cache group
- naming
- select chunks
- select modules
=================================================
更新2018-07-04
Tree shaking
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如
import
和export
。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。
过去我们使用webpack进行tree shaking有好多坑,因为Babel为了符合ES6真正的语义,编译类时采取了Object.defineProperty
来定义原型方法,这导致一些我们原本看似没有副作用的代码,便转化为了(可能)有副作用的。关于这块内容可以参考这篇文章你的Tree-Shaking并没什么卵用 里的详细解析,我也是从中得到许多启发。
今天主要了解一下webpack 4对于tree shaking做了哪些工作。新的webpack 4中,可以通过package.json
的"sideEffects"
属性作为标记,会对编译器表明项目中哪些文件是"pure(纯的ES2015 模块)",由此可以安全的删除文件中未使用的部分。
如果所有代码都不包含副作用,我们就可以简单地将该属性标记为false
;
「副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。
如果只是部分代码会存在一些副作用,那么给它提供一个数组:
{
"name": "your-project",
"sideEffects": [
"./src/some-side-effectful-file.js"
]
}
数组方式支持相关文件的相对路径、绝对路径和glob模式。
压缩输出
通过以上的方式,我们已经可以找出那些需要删除的未使用代码(dead code),但我们还要将它们删除。通过uglifyjs压缩可以将其删除。而在webpack 4中,我们可以直接使用"mode"
设置为"production"
来启用UglifyJsPlugin
。
这样就好啦~