webpack 4.0.0-beta.0版本新特性介绍


Posted in Javascript onFebruary 10, 2018

近年来前端技术如雨后春笋般蓬勃发展,我们也在这个潮流下不断地学习、成长。前端技术的不断发展,给我们提供了许多的便利。例如:JSX的出现为我们提供了一个清晰、直观的方式来描述组件树,LESS/SASS的出现提高了我们书写css的能力,AMD/CommonJS/ES6 的出现为我们模块化开发提供了便利。然而,我们需要使用其它工具将这些工具转化成原生语言以运行在浏览器上。为了能够更好的将这些不同的资源整合到一起,我们就需要一个打包工具,webpack就是这个需求下的产物。
webpack 可以看做是模块打包机。它做的事情是:分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。目前,webpack 总共发布了三个稳定版本。从17年八月底开始,经历了长达五个月的开发周期,webpack 团队通过增加大量新特性、bug修复、问题改善并于近期发布了 webpack 4.0.0 的 beta 版本。如果你对 webpack 感兴趣,下面我们就来学习一下 webpack 4.0.0-beta.0 的新特性。
P.S. 以下所有代码演示代码都是基于 webpack 4.0.0-beta.0。

1、安装webpack v4.0.0-beta.0

如果你使用yarn:

yarn add webpack@next webpack-cli --dev

如果你使用npm:

npm install webpack@next webpack-cli --save-dev

2、webpack 4.0.0.beta.0 新特性介绍

下面是一些你肯定会感兴趣的新特性。如果阅读完本章后还觉得不过瘾,你可以再这查看完整的changelog。

本章将从以下几部分来介绍 webpack 4.0.0-beta.0。

2.1 环境

webpack 运行环境升级。已经不支持 Node.js 4 版本。源码升级到更高的 ECMAScript 版本。

根据 webpack package.json 配置中显示 Node.js 最低支持版本:”node”: “>=6.11.5”

2.2 模块

webpack 模块类型及 .mjs 的支持:

长久以来,JS是webapck中唯一的模块类型。正因此,开发者无法有效地打包其它类型的文件。目前,webpack实现了五种模块类型,它们各有自己的优势,可按需要使用(后面会详细说明)。

  1. javascript/auto: (webpack3中默认)支持所有的JS模块系统:CommonJS、AMD、ESM。
  2. javascript/esm: EcmaScript模块,所有其他模块系统不可用(.mjs文件中默认)。
  3. javascript/dynamic: 不支持CommonJS和EcmaScript模块。
  4. json: JSON数据,可以通过require和import导入(.json文件默认)。
  5. webassembly/experimental: WebAssembly模式(目前处于实验性阶段,.wasm文件默认)。

用法:

module.rules 中的 type 就是新增加的属性,用来支持不同的模块类型。

module: {
  rules: [{
    test: /\.special\.json$/,
    type: "javascript/auto",
    use: "special-loader"
  }]
 }

此外,现在webpack 按照 .wasm, .mjs, .js, 以及 .json 等扩展名的顺序来解析。

javascript/esm 相比于 javascript/auto 处理ESM更加严格:
具体表现在两个方面:1. 导入的名称必须存在于导入的模块中。2. 动态的模块(非ESM,例如CommonJS)只能通过默认 import 导入,其他所有(包括命名空间导入)的导入都会报错。

2.3 用法

必须在 “开发或者生产” 中选择一种模式(这里有一种隐藏模式 none,可以禁用一切功能)。

1)生产模式不支持监听,开发模式针对快速增量重建进行了优化。
2)生产模式同样支持模块串联,即变量提升(此功能在webpack 3 中已经实现)。
3)开发模式下支持注释和提示,并且支持 eval 的source map。

将 CLI 移动到 webpack-cli 中,你需要通过安装 webpack-cli 使用 CLI。

你可以使用 optimization.* 标志来配置自己的自定义模式。

webpackInclude 和 webpackExclude 可以通过神奇的注释来支持 import() ,他们允许在使用动态表达式时过滤文件。
使用 System.import() 会发出警告:

1)可以使用 Rule.parser.system:true 关闭警告。
2)你也可以使用 Rule.parser.system:false 关闭 System.import()。

对于迁移到新的插件系统的插件 ProgressPlugin 现在显示插件名称。

webpack 现在可以本地处理 JSON。如果用 loader 转换 json 为 js,需要设置: type:”javascript/auto”。当然,不用 loader webpack 依然可以正常工作。

2.4 配置

删除了一些常用内置插件:

1)NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors (生产模式默认)。
2)ModuleConcatenationPlugin -> optimization.concatenateModules (生产模式默认)。
3)NamedModulesPlugin -> optimization.namedModules (开发模式默认)。

删除了常用的 CommonsChunkPlugin -> optimization.splitChunks对于那些需要细粒度控制缓存策略的人,可以通过 optimization.splitChunks和 optimization.runtimeChunk。 现在可以使用 module.rules[].resolve来配置解析。它与全局配置合并。

optimization.minimize 用于控制minimizing的开关。 生产模式默认为开,开发模式默认为关。

optimization.minimizer 用于配置minimizers和选项。

许多支持占位符的配置选项现在也支持函数形式。

错误的 options.dependencies 配置现在会抛出异常。

sideEffects 可以通过 module.rules 覆盖。

添加 output.globalObject 配置选项以允许在运行时选择全局对象引用。

无需显式设置entry和output属性,webpack默认设置entry属性为./src,output的属性为./dist。

移除module.loaders。

2.5 优化

uglifyjs-webpack-plugin 升级到了 v 1,并且支持 ES6语法。

可以在 package.json 中配置 sideEffects:false 。当设置这个字段之后,标识在使用的库里没有任何副作用。这意味着webpack可以从代码中安全地清除任何re-exports。

使用JSONP数组来代替JSONP函数 ?> 异步支持。

引入新的 optimization.splitChunks 选项。

webpack 可以删除无用代码,之前是由 Uglify 删除无用的代码,现在 webpack 也可以删除无用的代码。这可以有效防止在 import 无用的代码之后发生的崩溃。

以下是一些内部优化:
1)用 tap 调用替换 plugin 调用(新的插件系统)。
2)将许多废弃的插件迁移到新的插件系统API。
3)为 json 模块添加 buildMeta.exportsType:default。
4)删除了 Parser (parserStringArray, parserCalculatedStringArray) 中未使用的方法。

2.6 性能

默认情况,UglifyJS 默认缓存和并行化(并未完全实现缓存和并行化,webpack5的里程碑)。

发布了一个新版本的插件系统,所以事件钩子和处理程序变的单一化。

多个性能改进,特别是更快的增量重建。

改进了RemoveParentModluesPlugin的性能。

2.7 不兼容的改变(插件、loader相关)

新的插件系统:

1)插件方法是向后兼容的
2)插件现在应该这样使用 Compiler.hooks.xxx.tap(<plugin name>, fn)

Chunk.chunks/parents/blocks 不再是数组。在内部使用一个集合,并且有方法来访问它。

Parser.scope.renames 和 Parser.scope.definitions 不再是对象/数组,而是Map/Set。

解析器使用 StackedSetMap(类似于LevelDB的数据结构)而不是数组。

在应用插件时不再设置 Compiler.options。

所有模块的构造参数都发生了变化。

将 options 合并到 ContextModule 和 resolveDependencies 的 options 对象中.

更改并重命名 import() 的依赖关系

将 Compiler.resolvers 移入可通过插件访问的 Compiler.resolverFactory中。

Dependency.isEqualResource 已被替换为 Dependency.getResourceIdentifier

Template 方法都是静态的。

已经添加了一个新的 RuntimeTemplate 类,outputOptions 和 requestShortener 已经被移动到这个类中。

1)已经更新了许多方法来代替 RuntimeTemplate 的使用。
2)我们计划将访问运行时的代码移动到这个新类中

Module.meta已被Module.buildMeta所取代

已添加Module.buildInfo和Module.factoryMeta

Module的一些属性已经被移动到新的对象中

添加指向上下文选项的 loaderContext.rootContext。loaders 可以使用它来创建相对于应用程序根目录的东西。

当启用HMR时,将 this.hot 标志添加到 loader 上下文中。

buildMeta.harmony 已被替换为 buildMeta.exportsType:namespace。

chunk 图已经改变:

之前:Chunks 的连接与嵌套依赖关系有关。
现在:ChunksGroups 的连接与引用依赖有关,按照顺序串联。
之前:AsyncDependenciesBlocks 按顺序引用 Chunks 列表。
现在:AsyncDependenciesBlocks 引用一个 ChunkGroup。

★★ 注意:以上内容都是关于 loaders、plugins 重大的变化。

3、重点更新详解

3.1 更好的默认值

直到今日,webpack 总是要求显式地设置 entry 和 output 属性。webpack 4.0.0-beta.0 中,webpack 会自动设定你的 entry 属性为 ./src 以及 output 的属性为 ./dist。
这意味着您不再需要配置文件来启动 webpack。接下来我们为你演示webpack 4.0.0-beta.0的便捷操作:

1、我们需要安装好 webpack 之后,在 package.json 中添加如下脚本即可启动:

"scripts": {
  "build": "webpack"
 },

2、在工程中添加简单示例代码如下图(整个工程没有 webpack 配置文件,即可运行打包):

webpack 4.0.0-beta.0版本新特性介绍

3、打包过程中我们发现有新特性的提示:

WARNING in configuration
The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment.

这就是我们下节要说的内容模式设置。

★★ 注意:入口默认为 ./src 如果缺少此文件夹会报错!

> webpack --mode production
ERROR in Entry module not found: Error: Can't resolve './src' in 'D:\workspace\github\Webpack-Example'

3.2 模式设置

以往的项目使用 webpack3 脚手架生成项目初始模板都会有两个甚至三个配置文件,比如
webpack.base.conf.js、webpack.prod.conf.js、webpack.dev.conf.js 而现在可以做到一个配置文件都不需要,直接在启动命令中传入参数 --mode development | production 达到区分不同模式的效果。

接下来修改 package.json 设置不同的模式:

"scripts": {
   "dev": "webpack --mode development",
   "build": "webpack --mode production"
 },

重新执行 npm run dev 或 npm run build 即可看到不同的打包结果:

webpack 4.0.0-beta.0版本新特性介绍

我们可以看到两种模式的结果完全不同,下面我们会更深入的按照我们真实的需求来讲解一些常用配置。

接下来这个配置是最常用到的,我们使用 webpack 的主要目的之一就是为了更好的支撑前段模块化的能力,既然需要模块化当然少不了代码分割,目前代码分割有以下几种:

  1.  通过 entry 分割不同入口,常用于多页应用;
  2.  通过 CommonsChunkPlugin 插件来分割不同功能模块;
  3.  通过动态 import 来分割。

下面我们主要讲解 webpack 4.0.0-beta.0 版本的重大变化删除了 CommonsChunkPlugin 插件。

3.3 删除 CommonsChunkPlugin

webpack 4.0.0-beta.0删除了 CommonsChunkPlugin,以支持两个新的选项(optimization.splitChunks 和 optimization.runtimeChunk)。

从webpack 4.0.0-beta.0 开始分割 Chunk 将不在使用 CommonsChunkPlugin 插件,而是使用 optimization 配置项,具体的实现原理可以参考 CommonsChunkPlugin。

由于还没有正式官方文档出来,以下是我们通过实践出的 optimization 配置方法:
其中用到了新增的 splitChunks 属性,此属性看字面意思就明白是分割代码块的选项,其下可配置项已在下面示例代码中列出(有兴趣的朋友可以自行实践):

entry: {
   vendor: ['lodash']
},
 
...
 
optimization: {
   splitChunks: {
   chunks: "initial", // 必须三选一: "initial" | "all"(默认就是all) | "async" 
   minSize: 0, // 最小尺寸,默认0
   minChunks: 1, // 最小 chunk ,默认1
   maxAsyncRequests: 1, // 最大异步请求数, 默认1
   maxInitialRequests : 1, // 最大初始化请求书,默认1
   name: function(){}, // 名称,此选项可接收 function
   cacheGroups:{ // 这里开始设置缓存的 chunks
     priority: 0, // 缓存组优先级
     vendor: { // key 为entry中定义的 入口名称
       chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是异步) 
       test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
       name: "vendor", // 要缓存的 分隔出来的 chunk 名称 
       minSize: 0,
       minChunks: 1,
       enforce: true,
       maxAsyncRequests: 1, // 最大异步请求数, 默认1
       maxInitialRequests : 1, // 最大初始化请求书,默认1
       reuseExistingChunk: true // 可设置是否重用该chunk(查看源码没有发现默认值)
     }
   }
 }
 },

以上就是 optimization.splitChunks 的所有可用的配置项属性。

总结

以上就是我们初步整理的关于 webpack 4.0.0-beta.0 的新特性,包含了一部分的官方更新日志的翻译,还有我们自己试验的一些属性。当然如果你有兴趣,也可以等到正式的官方文档发布之后进行实践。
如果上面的信息不能够完全满足你的兴趣,还请关注官方日志。在未来不到一个月的时间里,webpack 将对插件、加载器以及整个生态系统进行更加严格的测试,并发布最终的官方稳定版本。如果你喜欢 webpack,你可以参与使用 webpack 4.0.0-beta.0。测试阶段发现、解决的问题越多,正式版本才会更加稳定。

示例代码

京东前端

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
用js实现键盘方向键翻页功能的代码
Jun 03 Javascript
javascript中的变量作用域以及变量提升详细介绍
Oct 24 Javascript
JS+CSS实现带有碰撞缓冲效果的竖向导航条代码
Sep 15 Javascript
Jquery技巧(必须掌握)
Mar 16 Javascript
JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍
May 19 Javascript
使用JavaScript实现表格编辑器(实例讲解)
Aug 02 Javascript
9种使用Chrome Firefox 自带调试工具调试javascript技巧
Dec 22 Javascript
vue打包之后生成一个配置文件修改接口的方法
Dec 09 Javascript
ES6入门教程之Array.from()方法
Mar 23 Javascript
JavaScript强制类型转换和隐式类型转换操作示例
May 01 Javascript
vue-axios同时请求多个接口 等所有接口全部加载完成再处理操作
Nov 09 Javascript
JavaScript实现登录窗体
Jun 22 Javascript
利用SpringMVC过滤器解决vue跨域请求的问题
Feb 10 #Javascript
Vue组件和Route的生命周期实例详解
Feb 10 #Javascript
Vue2.0用户权限控制解决方案的示例
Feb 10 #Javascript
vue.js 微信支付前端代码分享
Feb 10 #Javascript
详解如何实现一个简单的 vuex
Feb 10 #Javascript
vue实现微信分享朋友圈,发送朋友的示例讲解
Feb 10 #Javascript
使用 vue.js 构建大型单页应用
Feb 10 #Javascript
You might like
PHP print类函数使用总结
2010/06/25 PHP
thinkphp3.2.2前后台公用类架构问题分析
2014/11/25 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
php使用APC实现实时上传进度条功能
2015/10/26 PHP
注意!PHP 7中不要做的10件事
2016/09/18 PHP
js实现DIV的一些简单控制
2007/06/04 Javascript
用户注册常用javascript代码
2009/08/29 Javascript
javascript Keycode对照表
2009/10/24 Javascript
jquery实现点击TreeView文本父节点展开/折叠子节点
2013/01/10 Javascript
微信小程序 网络API 上传、下载详解
2016/11/09 Javascript
js拖拽功能实现代码解析
2016/11/28 Javascript
微信小程序 slider 详解及实例代码
2017/01/10 Javascript
React组件之间的通信的实例代码
2017/06/27 Javascript
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
2018/06/05 jQuery
Vue使用lodop实现打印小结
2019/07/06 Javascript
ubuntu系统下 python链接mysql数据库的方法
2017/01/09 Python
python实现控制台打印的方法
2019/01/12 Python
python整合ffmpeg实现视频文件的批量转换
2019/05/31 Python
使用Python中的reduce()函数求积的实例
2019/06/28 Python
Python系统公网私网流量监控实现流程
2020/11/23 Python
SpringBoot首页设置解析(推荐)
2021/02/11 Python
HTML5通过navigator.mediaDevices.getUserMedia调用手机摄像头问题
2020/04/27 HTML / CSS
夏尔巴人登珠峰品牌:Sherpa Adventure Gear
2018/02/08 全球购物
蒙蒂塞罗商店:Monticello Shop
2018/11/25 全球购物
俄罗斯外国汽车和国产汽车配件网上商店:Движком
2020/04/19 全球购物
摄影实习自我鉴定
2013/09/20 职场文书
大学在校生求职信范文
2013/11/21 职场文书
商场促销活动方案
2014/02/08 职场文书
工程师岗位职责规定
2014/02/26 职场文书
员工生日会策划方案
2014/06/14 职场文书
责任书格式
2015/01/29 职场文书
户外活动总结
2015/02/04 职场文书
慰问信格式
2015/02/14 职场文书
教你怎么用Python监控愉客行车程
2021/04/29 Python
一文读懂navicat for mysql基础知识
2021/05/31 MySQL
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
2021/06/26 MySQL