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 相关文章推荐
javascript innerText和innerHtml应用
Jan 28 Javascript
jQuery 1.5最新版本的改进细节分析
Jan 19 Javascript
使用js的replace()方法查找字符示例代码
Oct 28 Javascript
2014年最火的Node.JS后端框架推荐
Oct 27 Javascript
浅析JavaScript事件和方法
Feb 28 Javascript
JS动态修改图片的URL(src)的方法
Apr 01 Javascript
jquery实现输入框实时输入触发事件代码
Dec 21 Javascript
如何利用JQuery实现从底部回到顶部的功能
Dec 27 Javascript
React-intl 实现多语言的示例代码
Nov 03 Javascript
vue-cli启动本地服务局域网不能访问的原因分析
Jan 22 Javascript
Node.js 实现简单的无侵入式缓存框架的方法
Jul 21 Javascript
JavaScript实现多球运动效果
Sep 07 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提示Failed to write session data错误的解决方法
2014/12/17 PHP
PHP 生成N个不重复的随机数
2015/01/21 PHP
php判断两个浮点数是否相等的方法
2015/03/14 PHP
php删除数组中重复元素的方法
2015/12/22 PHP
PHP设置头信息及取得返回头信息的方法
2016/01/25 PHP
thinkPHP3.2使用RBAC实现权限管理的实现
2019/08/27 PHP
基于PHP+Mysql简单实现了图书购物车系统的实例详解
2020/08/06 PHP
js以对象为索引的关联数组
2010/07/04 Javascript
基于jQuery全屏焦点图左右切换插件responsiveslides
2015/09/07 Javascript
jQuery+canvas实现的球体平抛及颜色动态变换效果
2016/01/28 Javascript
探讨JavaScript语句的执行过程
2016/01/28 Javascript
javascript基础知识
2016/06/07 Javascript
浅谈jquery点击label触发2次的问题
2016/06/12 Javascript
JS实现漂亮的时间选择框效果
2016/08/20 Javascript
JavaScript 动态三角函数实例详解
2017/01/08 Javascript
js判断文件类型大小并给出提示的实现方法
2018/01/03 Javascript
vue实现的微信机器人聊天功能案例【附源码下载】
2019/02/18 Javascript
在 Vue 中编写 SVG 图标组件的方法
2020/02/24 Javascript
详解uniapp的全局变量实现方式
2021/01/11 Javascript
python解析html提取数据,并生成word文档实例解析
2018/01/22 Python
python 执行shell命令并将结果保存的实例
2018/05/11 Python
Flask Web开发入门之文件上传(八)
2018/08/17 Python
opencv+pyQt5实现图片阈值编辑器/寻色块阈值利器
2020/11/13 Python
CSS3 渐变(Gradients)之CSS3 径向渐变
2016/07/08 HTML / CSS
CSS3 实用技巧:实现黑白图像效果示例代码
2013/07/11 HTML / CSS
HTML5中微数据概述及在搜索引擎中的使用举例
2013/02/07 HTML / CSS
泰国在线书店:SE-ED
2020/06/21 全球购物
Linux常见面试题
2016/10/04 面试题
二手书店创业计划书
2014/01/16 职场文书
《美丽的小路》教学反思
2014/02/26 职场文书
本科应届生求职信
2014/08/05 职场文书
个人遵守党的政治纪律情况对照检查材料思想汇报
2014/09/25 职场文书
2014年效能监察工作总结
2014/11/21 职场文书
2014年物流工作总结
2014/11/25 职场文书
深度好文:50条没人告诉你的人生经验,句句精辟
2019/08/22 职场文书
Redis实现主从复制方式(Master&Slave)
2022/06/21 Redis