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 相关文章推荐
IE 缓存策略的BUG的解决方法
Jul 21 Javascript
javascript实现字符串反转的方法
Feb 05 Javascript
JavaScript跨平台的开源框架NativeScript
Mar 24 Javascript
javascript中scrollTop详解
Apr 13 Javascript
一个炫酷的Bootstrap导航菜单
Dec 28 Javascript
js/jq仿window文件夹移动/剪切/复制等操作代码
Mar 08 Javascript
angularjs项目的页面跳转如何实现(5种方法)
May 25 Javascript
ES6新增数据结构WeakSet的用法详解
Aug 07 Javascript
vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)
Sep 05 Javascript
微信小程序如何播放腾讯视频的实现
Sep 20 Javascript
vue+echarts实现动态折线图的方法与注意
Sep 01 Javascript
详解TypeScript中的类型保护
Apr 29 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
关于Zend Studio 配色方案插件的介绍
2013/06/24 PHP
PHP 导出Excel示例分享
2014/08/18 PHP
ThinkPHP模板标签eq if 中区分0,null,false的方法
2017/03/24 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
2019/03/11 PHP
深入理解JavaScript系列(47):对象创建模式(上篇)
2015/03/04 Javascript
原生JS实现风箱式demo,并封装了一个运动框架(实例代码)
2016/07/22 Javascript
AngularJS延迟加载html template
2016/07/27 Javascript
jquery把int类型转换成字符串类型的方法
2016/10/07 Javascript
谈谈第三方App接入微信登录 解读
2016/12/27 Javascript
nodejs利用ajax实现网页无刷新上传图片实例代码
2017/06/06 NodeJs
JS非空验证及邮箱验证的实例
2017/08/11 Javascript
Iphone手机、安卓手机浏览器控制默认缩放大小的方法总结(附代码)
2017/08/18 Javascript
使用SVG基本操作API的实例讲解
2017/09/14 Javascript
JavaScript 数组去重并统计重复元素出现的次数实例
2017/12/14 Javascript
详解Vue SPA项目优化小记
2018/07/03 Javascript
Vuejs+vue-router打包+Nginx配置的实例
2018/09/20 Javascript
利用原生的JavaScript实现简单拼图游戏
2018/11/18 Javascript
jquery实现两个div中的元素相互拖动的方法分析
2020/04/05 jQuery
JS实现简单贪吃蛇小游戏
2020/10/28 Javascript
python 解析html之BeautifulSoup
2009/07/07 Python
python查找指定具有相同内容文件的方法
2015/06/28 Python
Python中的变量和作用域详解
2016/07/13 Python
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
梅尔倒谱系数(MFCC)实现
2019/06/19 Python
Python实现二叉搜索树BST的方法示例
2019/07/30 Python
wxPython实现分隔窗口
2019/11/19 Python
python利用JMeter测试Tornado的多线程
2020/01/12 Python
快速查找Python安装路径方法
2020/02/06 Python
如何理解python对象
2020/06/21 Python
菲律宾票务网站:StubHub菲律宾
2018/04/21 全球购物
酒店采购员岗位职责
2014/03/14 职场文书
爱护环境建议书
2015/09/14 职场文书
大学毕业生自我鉴定范文
2019/06/21 职场文书
助学金申请书该怎么写?
2019/07/16 职场文书
淡雅古典唯美少女娇媚宁静迷人写真
2022/03/21 杂记