Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >显微镜下的webpack4的新特性:mode详解

显微镜下的webpack4的新特性:mode详解

作者头像
小美娜娜
发布于 2019-04-04 06:56:57
发布于 2019-04-04 06:56:57
91200
代码可运行
举报
文章被收录于专栏:小美娜娜小美娜娜
运行总次数:0
代码可运行

webpack4支持的一个新特性就是zero配置,不需要config,也可以打包,这对于懒癌患者很有诱惑力,但是这也意味着我们不清楚零配置发生了写什么,也不知道打包出来的文件是否符合我们的心意,全部都是佛系打包。不过作为项目的亲爹亲妈,还是要对自己的孩子负责,每个打包过程都是要可控的。本文就是详解不同mode下,webpack打包都发生了些什么事。

我们来看一下MODE这个参数,他有三个参数productiondevelopmentnone,前两个是有预设的插件,而最后一个则是什么都没有,也就是说设置为none的话,webpack就是最初的样子,无任何预设,需要从无到有开始配置。

在webpack的配置中,其他配置都可以没有!但是mode是必备的,如果不加mode,官方虽然会打包,但同时也会给你一个警告:

WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: webpack.js.org/concepts/mo…

意思很简单,就是mode没有被设置的情况下,系统就会给你一个默认的production模式。

mode配置很简单,就只有3个值,任君挑选。none这个参数,相信大家都能理解,那么我们就研究下其他两个productiondevelopment,这为什么要有这两个状态,以及两者在webpack打包中都干了些啥事。

如何在打包中区分productiondevelopment的状态

在mode为productiondevelopment的状态下,为了兼顾两个状态下的程序运行,webpack创建了一个全局变量process.env.NODE_ENV,等同于在插件plugins中加入了new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development|production") }),用来区分不同的状态,同时可以在程序中区分程序状态。

那么我们该如何在coding的时候进行区分呢?因为process.env.NODE_ENV是全局变脸给,所以可以这样来引用值,假设mode:production

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ("development" === process.env.NODE_ENV){
    ....
}else{
    ....
}
复制代码

编译之后:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ("development" === "production"){
    ....
}else{
    ....
}
复制代码

也就是最后process.env.NODE_ENV会被替换为一个常量。这个小功能可以帮助我们在写业务JS的时候,区分线上版本与开发版本。

none模式下的模块打包

在没有任何优化处理的情况下,按照webpack默认的情况下打包出来的模块是怎么样的呢?下方是一个简易的例子,我们可以看出,他将模块打包至数组之中,调用模块的时候,就是直接调用模块在此数组中的一个序号。然后没有压缩混淆之类的优化,连注释都帮我们标的好好的,比如导入 /* harmony import / ,/ harmony default export */。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
    /* 0 */
    (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    /* harmony import */ var _page2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
    console.log(_page2_js__WEBPACK_IMPORTED_MODULE_0__["default"])
    }),
    /* 1 */
    (function(module, __webpack_exports__, __webpack_require__) {
    "use strict";
    __webpack_require__.r(__webpack_exports__);
    let str="page1"
    /* harmony default export */ __webpack_exports__["default"] = (str);
    })
]
复制代码

但是无论是在开发环境development下,还是在正式坏境production下,这个代码都是不过关的,对于开发环境,此代码可读性太差,对于正式环境,此代码不够简洁,因此,为了减少一些重复操作,webpack4提供的development|production可以很大程度上帮我们做掉一大部分事,我们要做的就是在这些事的基础上加功能。

development模式下,webpack做了那些打包工作

development是告诉程序,我现在是开发状态,也就是打包出来的内容要对开发友好。在此mode下,就做了以下插件的事,其他都没做,所以这些插件可以省略。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// webpack.development.config.js
module.exports = {
+ mode: 'development'
- devtool: 'eval',
- plugins: [
-   new webpack.NamedModulesPlugin(),
-   new webpack.NamedChunksPlugin(),
-   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}
复制代码

我们看看NamedModulesPluginNamedChunksPlugin这两个插件都做了啥,原本我们的webpack并不会给打包的模块加上姓名,一般都是按照序号来,从0开始,然后加载第几个模块。这个对机器来说无所谓,查找载入很快,但是对于人脑来说就是灾难了,所以这个时候给各个模块加上姓名,便于开发的时候查找。

没有NamedModulesPlugin,模块就是一个数组,引用也是按照在数组中的顺序引用,新增减模块都会导致序号的变化,就是webpack默认打包下的情况,参考上一节。

有了NamedModulesPlugin,模块都拥有了姓名,而且都是独一无二的key,不管新增减多少模块,模块的key都是固定的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{

"./src/index.js":   (function(module, __webpack_exports__, __webpack_require__) {
                        "use strict";
                        __webpack_require__.r(__webpack_exports__);
                        var _page2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/page2.js");
                        console.log(_page2_js__WEBPACK_IMPORTED_MODULE_0__["default"])
                    }),
"./src/page2.js":    (function(module, __webpack_exports__, __webpack_require__) {
                        "use strict";
                        __webpack_require__.r(__webpack_exports__);
                        let str="page1"
                         __webpack_exports__["default"] = (str);
                    })
}
复制代码

除了NamedModulesPlugin,还有一个NamedChunksPlugin,这个是给配置的每个chunks命名,原本的chunks也是数组,没有姓名。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
             Asset      Size  Chunks             Chunk Names
          index.js  4.04 KiB       0  [emitted]  index
          page2.js  3.75 KiB       1  [emitted]  page2
复制代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
             Asset      Size           Chunks             Chunk Names
          index.js   4.1 KiB            index  [emitted]  index
          page1.js  4.15 KiB            page1  [emitted]  page1
复制代码

NamedChunksPlugin其实就提供了一个功能就是你可以自定义chunks的名字,假如我再不同的包中有相同chunk名,怎么办?这个时候就要在进行区分了,我么可以用所有的依赖模块名加本上的模块名。因为Chunk.modules已经废弃了,现在用其他的方法来代替chunk.mapModules,然后重命名chunk的名字:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
new webpack.NamedChunksPlugin((chunk) => {
    return chunk.mapModules(m => {
        return path.relative(m.context, m.request)
    }).join("_")
}),      
复制代码

看一眼做这一行代码的效果,我们可以看到Chunks这边已经重命名了,这样可以很大程度上解决chunks重名的问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
             Asset      Size             Chunks             Chunk Names
          index.js   4.1 KiB  index.js_page2.js  [emitted]  index
          page2.js  3.78 KiB           page2.js  [emitted]  page2
复制代码

总结:development也就给我们省略了命名的过程,其他的还是要自己加的。

production

在正式版本中,所省略的插件们,如下所示,我们会一个个分析。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// webpack.production.config.js
module.exports = {
+  mode: 'production',
-  plugins: [
-    new UglifyJsPlugin(/* ... */),
-    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
-    new webpack.optimize.ModuleConcatenationPlugin(),
-    new webpack.NoEmitOnErrorsPlugin()
-  ]
}
复制代码

UglifyJsPlugin

我们第一个需要处理的就要混淆&压缩JS了吧,这个时候就要请出UglifyJs了,在webpack中他的名字是const UglifyJsPlugin = require('uglifyjs-webpack-plugin');,这样就可以使用他了。

不过new UglifyJsPlugin(),这个插件我们可以在optimize中配置,效果是一样的,那么我们是不是就不用再导入一个新的插件了,这样反而会拖慢webpack的就打包速度。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
optimization:{
    minimize: true,
},
复制代码

将插件去除,混淆压缩放入optimization,这样webpack速度快的飞起了。只有第一次打包会慢,之后再打包就快了。

ModuleConcatenationPlugin

webpack.optimize.ModuleConcatenationPlugin()这个插件的作用是什么呢?官方文档上是这么描述的:

记住,此插件仅适用于由 webpack 直接处理的 ES6 模块。在使用转译器(transpiler)时,你需要禁用对模块的处理(例如 Babel 中的 modules 选项)。

NoEmitOnErrorsPlugin

最后一个插件就是webpack.NoEmitOnErrorsPlugin(),这个就是用于防止程序报错,就算有错误也给我继续编译,很暴力的做法呢。

others

还有一些默认的插件配置,也就是可以不在plugins中引用的配置:

flagIncludedChunks

flagIncludedChunks这个配置的作用是,看结果:

未启用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   Asset       Size  Chunks             Chunk Names
index.js   1.02 KiB       0  [emitted]  index
page1.js  970 bytes       1  [emitted]  page1
复制代码

启用后,如果只有二个文件似乎表现不明显,于是我增加了三个文件,page1调用page2,index调用page1,那么一目了然,在这里的chunks就是所有引用模块的id。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  Asset       Size   Chunks             Chunk Names
index.js   1.08 KiB  0, 1, 2  [emitted]  index
page1.js   1.01 KiB     1, 2  [emitted]  page1
page2.js  971 bytes        2  [emitted]  page2
复制代码
OccurrenceOrderPlugin

webpack.optimize.OccurrenceOrderPlugin这个插件的作用是按照chunk引用次数来安排出现顺序,因为这让经常引用的模块和chunk拥有更小的id。将上面的例子加上这个配置运行下就是这样的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   Asset       Size   Chunks             Chunk Names
page2.js  969 bytes        0  [emitted]  page2
page1.js   1.01 KiB     1, 0  [emitted]  page1
index.js   1.08 KiB  2, 0, 1  [emitted]  index
复制代码
SideEffectsFlagPlugin

webpack.optimize.SideEffectsFlagPlugin()这个插件如果需要生效的话,需要两个条件,一个是导入的模块已经标记了sideEffect,即package.json中的sideEffects这个属性为false,第二个就是当前模块引用了次无副作用的模块,而且没有使用。那么在打包的时候,就不会将这个模块打包到文件中。

总结

实际上production mode下,与官方文档相比,他的配置更加等同于如下配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module.exports = {
    mode:"none",
    optimization:{
        flagIncludedChunks:true,
        minimize: true,
    },
    plugins: [
        new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        new webpack.optimize.SideEffectsFlagPlugin()
    ]
}
复制代码

production各插件参考文档

name

effect

FlagDependencyUsagePlugin

标记没有用到的依赖,这个插件无法通过webpack获取,我只能通过强行导入webpack/lib下的class文件来导入。

SideEffectsFlagPlugin

用于处理tree shaking的,tree shaking,sideEffect这个插件的作用就是,如果当前的模块没有引用,而且package.json中的sideEffects为false,那么打包的时候就可以将此包剔除。stackoverflow上有用的答案

FlagIncludedChunksPlugin

给当前chunk包含的chunkid加入chunk名之中

ModuleConcatenationPlugin

作用域提升

NoEmitOnErrorsPlugin

阻止任何报错

OccurrenceOrderPlugin

按照调用次数来给chunks排序

UglifyJsPlugin

混淆压缩

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年10月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
编辑精选文章
换一批
显微镜下的webpack4入门
前端的构建打包工具很多,比如grunt,gulp。相信这两者大家应该是耳熟能详的,上手相对简单,而且所需手敲的代码都是比较简单的。然后webpack的出现,让这两者打包工具都有点失宠了。webpack比起前两者打包工具,对于前端程序员JS编程能力的要求还是挺高的。不过需要兼容ie8及以下的小伙伴们,就不要考虑webpack了,他很傲娇地不兼容!
小美娜娜
2019/04/04
6660
显微镜下的webpack4入门
webpack4 新特性
wepack4 出来已经有半年了,目前最新的 release 版本为 4.19.0。由于之前项目打包一直存在性能问题,所以我一直很关注 webpack 和其社区的发展。目前来说 webpack4 已经趋于稳定,很多关键的插件也都更新了对 webpack4 的支持;更为重要的是,webpack4 的官方文档(中英文)已经很完善了,因此现在不学习 webpack4,更待何时。根据 webpack 作者 Tobias Koppers 的说法,他们已经着手开始开发 webpack5 了。
李振
2021/11/26
1.3K0
webpack4 新特性
webpack中的模式(mode)
1.development 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。
刘亦枫
2020/03/19
8110
Webpack 4教程:为什么要优化代码
在本次Wepack 4教程,我们会聚焦通过压缩输出内容,来提升你应用的用户体验。这意味着,生产环境需要一套不同的做法。今天,我们将通过mode参数来讲述Webpack内置的优化功能。开始吧!
葡萄城控件
2019/05/25
5770
Webpack4 搭建 Vue 项目
由于 Parcel 打包工具的影响,webpack4 也追求零配置搭建项目。而前阵子出现的 vue-cli 3.0也是基于 webpack4 零配置的思想创建的。对于一些习惯webpack3 的开发者难免有些不习惯。本文就带你绕过 vue-cli,用 webpack4 一步步搭建 vue 项目。
小皮咖
2019/11/05
1.2K0
webpack4:连奏中的进化
webpack4在2月底的时候发布,这次webpack4有了一个名字"Legato",也就是"连奏"的意思,寓意webpack在不断进化,而且是无缝(no-gaps)的进化。webpack的进化点是通过捐赠者和用户投票来决定的,之前在介绍webpack3的时候,曾给出过投票数在前几名的优化点,集中在用户体验、构建性能(速度和产出大小)、通用和适配性(es module、typescript、web assemble)等。webpack4发布了,下面将结合文档和实践,验证一下webpack是否兑现了当初的诺
用户1217459
2018/05/29
1.4K0
webpack配置完全指南
对于入门选手来讲,webpack 配置项很多很重,如何快速配置一个可用于线上环境的 webpack 就是一件值得思考的事情。其实熟悉 webpack 之后会发现很简单,基础的配置可以分为以下几个方面: entry 、 output 、 mode 、 resolve 、 module 、 optimization 、 plugin 、 source map 、 performance 等,本文就来重点分析下这些部分。
gogo2027
2022/09/26
3.3K0
webpack 4 入门
写这篇文章是为了让自己在自学 webpack 的过程中有所产出,于是边读 webpack 中文文档 边写下了这篇文章,里面的很多实例都是直接挪用的文档中的实例,但在一些概念的理解上我加入了自己的想法「未必精确」,所以读的时候要抱着「怀疑的态度」。
Ryoma
2022/04/02
8080
前端-手摸手,带你用合理的姿势使用 webpack 4(上)
作者:华尔街见闻技术团队 - 花裤衩 segmentfault.com/a/1190000015919863 前几天 webpack 作者 Tobias Koppers 发布了一篇新的文章:we
grain先森
2019/03/29
1.3K0
前端-手摸手,带你用合理的姿势使用 webpack 4(上)
Webpack 性能系列五:使用 Scope Hoisting
默认情况下,经过 Webpack 打包后的模块资源会被组织成一个个函数形式,例如:
Tecvan
2021/12/09
1.6K0
前端工程化 - webpack 基础
默认配置文件 webpack.config.js,可以通过 webpack --config 指定配置文件
Cellinlab
2023/05/17
3350
WebPack高级进阶:
紧跟前文: WebPack5.0 快速入门 简单的了解了:WebPack的使用,接下来康康项目中的管理吧;
Java_慈祥
2024/08/01
2370
WebPack高级进阶:
webpack配置完全指南
首先webpack是一个静态模块打包器,所谓的静态模块,包括脚本、样式表和图片等等;webpack打包时首先遍历所有的静态资源,根据资源的引用,构建出一个依赖关系图,然后再将模块划分,打包出一个或多个bundle。再次白piao一下官网的图,生动的描述了这个过程:
gogo2027
2022/10/03
1.3K0
webpack深入浅出实战系列
https://github.com/luoxue-victor/learn_webpack/
前端迷
2020/02/19
1.7K0
webpack深入浅出实战系列
假如用王者荣耀的方式学习webpack
崴博.派克诞生于遥远西方的勇士之地,拥有着高超的机械技艺,善于运用各种工具来实现一些看似不可能完成的事。游历王者大陆时机缘巧合遇到了年轻的墨子,与之成为好友。后协助大宗师墨子建造了大陆第一雄城,被后人称为上古文明终结后最伟大的奇迹——长安!长安以“方舟”为驱动核心中枢,配合层出不断的机关,守护着华丽的大明宫。派克为人低调,不喜出现在大众视野,他是需求人性启迪的理想主义者,信奉着唯有光荣进化才能实现人类的全部潜能。
李文杨
2020/05/12
9610
webpack——快速入门【一】
https://github.com/webproblem/learning-article#webpack
思索
2024/08/16
1990
webpack——快速入门【一】
webpack4新特性介绍
当下最流行的模块打包器 webpack 于2018年2月25日正式发布v4.0.0版本,代号legato。从官方的 发布日志 来看, 本次大版本更新带来了很多新特性更新和改善,这将会让webpack的配置更加简单。本文,笔者将会全面介绍webpack4的新特性及实践。
腾讯IVWEB团队
2020/06/24
9010
Webpack模块打包器
通常我们会将 Webpack 安装到项目的依赖中,这样就可以使用项目本地版本的 Webpack。
乐心湖
2021/01/27
7520
Webpack模块打包器
从webpack4打包文件说起
一堆的webpack配置教程看腻了?这里有webpack4的打包及加载机制,要不了解一下?而这一切就得从打包文件说起。
elson
2018/08/01
3K1
webpack3 升级到 webpack4 小记
团队开发的时候,发现启动项目服务 npm run dev 很慢,我试了一下,要三四十秒,这对于我们开发来讲,会导致开发效率下降很多,而我们目前使用的是 webpack3,所以我想尝试通过升级 webpack 来提升一下编译打包的速度
GopalFeng
2020/09/24
1.2K0
webpack3 升级到 webpack4 小记
相关推荐
显微镜下的webpack4入门
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档