sideEffects 副作用

webpack4新增的功能。

允许通过配置的方式去标识代码是否有副作用,从而为 Tree Shaking 提供更多的压缩空间。

sideEffects 一般用于开发npm模块时,标记是否有副作用。

官方文档中将它和 Tree Shaking 放在一起讲,所以容易误解为它们是因果关系,实际上二者没什么关系。

副作用

副作用:模块执行时除了导出成员之外所作的事情。

例如一个模块中定义了其他内容:

export default () => {console.log('本模块不只导出一个默认成员,还做了一些其他事情')
}
// 以下是副作用代码
console.log('模块被使用')
window.foo = '往全局添加一个变量'

webpack 的 Tree Shaking 是 通过 usedExports 标记未使用的成员,打包时不生成导出它们的代码,从而通过minimize 移除它们。

所以 Tree Shaking 通过 usedExports 摇掉的是模块自己的代码中不被需要的部分。

但是导入这个模块的文件中,还保留了import代码,例如Tree Shaking示例打包后包裹/src/index.js的函数中会保留「导入模块行为」的代码。

// 打包结果中包裹 /src/index.js 的函数
(function(module, __webpack_exports__, __webpack_require__) {"use strict";__webpack_require__.r(__webpack_exports__);// 保留了「导入模块行为」的代码/* harmony import */ var _component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);document.body.append(Object(_component__WEBPACK_IMPORTED_MODULE_0__[/* Button */ "a"])());})

因为package.json中的sideEffects字段,默认为true,即默认这个npm包有副作用(其下模块们除了导出还做了其他事情)

并且webpack的当前配置下,也未指定是否处理无副作用的代码。

所以这些import代码被保留下来,自然,打包后,那些被import调用的模块,不管里面的成员是否被使用或者导出的内容是否为空,都会生成一个包裹它们的函数。

而这些函数,作为打包文件中,执行webpack方法的参数(一个数组)中的元素,自然不会被minimize删除。


例如将上面的/src/component.js中的成员分别单独创建一个文件(即「模块A」们),并在一个index.js(即「模块B」)文件中全部导入。

使用时直接导入这个index.js

// /src/components/button.js ---------------
export default () => {return document.createElement('button')
}// /src/components/link.js ---------------
export default () => {return document.createElement('a')
}// 添加一个副作用代码
document.write('This is a side effect code')// /src/components/heading.js ---------------
export default level => {return document.createElement('h' + level)
}// src/components/index.js ---------------
export { default as Button } from './button'
export { default as Link } from './link'
export { default as Heading } from './heading'// src/index.js ---------------
import { Button } from './components'document.body.append(Button())

沿用之前的示例,关闭babel的modules配置,optmization只启用usedExports。

// webpack.config.js
module.exports = {mode: 'none',module: {rules: [{test: /\.js$/,use: {loader: 'babel-loader',options: {presets: [ '@babel/preset-env' ]},},},],},optimization: {usedExports: true,// 压缩代码// minimize: true,},
}

打包查看结果,3个模块中的成员正常被标记已使用和未使用,但是/src/comonents/index.js中保留了3个模块的「导入」代码。

即使link和headingm没有副作用,导入它们已经没有了意义。

// 包裹/src/components/index.js的函数
(function(module, __webpack_exports__, __webpack_require__) {"use strict";// 导入button.js/* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);// 导出button.js/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _button__WEBPACK_IMPORTED_MODULE_0__["a"]; });// 虽然没有用到link和heading中的成员,但还是保留了「导入模块行为」的代码/* harmony import */ var _link__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);/* harmony import */ var _heading__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);})
webpack 和 package.json 中的 sideEffects

webpack通过配置optimization.sideEffectstrue,表示打包时跳过那些没有被使用的且被package.json标记为无副作用的模块。

表现为:

  1. webpack打包结果不会保留这些没有意义的「导入模块行为」的代码。
  2. webpack打包结果不会保留没有使用(导入)的模块。

开启后,webpack会去package.json中寻找sideEffects字段。

package.json中的sideEffects字段表示,当前项目中的模块是否有副作用,默认为true

webpack找到这个字段,且它定义的如果是false(当前项目中的模块无副作用)。

那么这些没有被用到的模块就不会被打包。

从而实现,一个模块中的成员全都没有被外部使用时,即这个模块没有被使用,这个模块就不会被打包进结果。

// package.json
{"sideEffects": false // 默认true,表示当前项目中的模块是否有副作用
}
// webpack.config.js
module.exports = {optimization: {sideEffects: true // 默认false,表示是否移除无副作用的模块usedExports: true,}
}

打包结果:

// 打包中函数的参数
[/* 0 */,/* 1 */,/* 2 */,/* 3 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";__webpack_require__.r(__webpack_exports__);/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);document.body.append(Object(_components__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"])());}),/* 4 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";/* harmony default export */ __webpack_exports__["a"] = (function () {return document.createElement('button');});})
]

对比下不移除无副作用代码的打包结果:

[/* 0 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";__webpack_require__.r(__webpack_exports__);/* harmony import */ var _components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);document.body.append(Object(_components__WEBPACK_IMPORTED_MODULE_0__[/* Button */ "a"])());}),/* 1 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";/* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _button__WEBPACK_IMPORTED_MODULE_0__["a"]; });/* harmony import */ var _link__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);/* harmony import */ var _heading__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);}),/* 2 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";/* harmony default export */ __webpack_exports__["a"] = (function () {return document.createElement('button');});}),/* 3 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";/* unused harmony default export */ var _unused_webpack_default_export = (function () {return document.createElement('a');});document.write('This is a side effect code');}),/* 4 */(function(module, __webpack_exports__, __webpack_require__) {"use strict";/* unused harmony default export */ var _unused_webpack_default_export = (function (level) {return document.createElement('h' + level);});})
]

注意:

package.json和webpack配置文件中的sideEffects虽然同名,但表示的意义不同。

  • package.json的sideEffects:标识当前package.json所影响的项目,当中所有的代码是否有副作用

    • 默认true,表示当前项目中的代码有副作用
  • webpack配置文件中的sideEffects:开启功能,是否移除无副作用的代码
    • 默认false,表示不移除无副作用的模块
    • 在production模式下自动开启。

webpack不会识别代码是否有副作用,只会读取package.json的sideEffects字段。

二者需要配合使用,才能处理无副作用的模块。

sideEffects 使用注意

使用webpack sideEffects功能的前提是,确保代码没有副作用。

否则webpack打包时就会误删那些有副作用的代码。

例如导入一个模块,它的内容是立即执行的,而不是通过导出成员等待被调用。

// /src/extend.js
window.onload = () => {alert('This is a side effect code')
}// /src/index.js
import './extend'

当使用sideEffects功能后,这个模块就不会被打包。

这样的场景通常是直接加载一个模块中的内容:

  • 加载立即执行的脚本
  • 加载 css 模块

解决办法:

  • 在package.json中关闭标识无副作用
  • 或者具体标识项目中哪些文件有副作用,webpack就不会忽略这些有副作用的模块
    • 这种方式,未被标识的模块,就会被当作无副作用处理
// package.json
{"sideEffects": ["./src/extend.js", // 标识有副作用的文件"*.css", // 也可以使用路径通配符"style/" // 注意目录必须带后面的/]
}

webpack二刷之五、生产环境优化(3.sideEffects 副作用)相关推荐

  1. 从零搭建webpack的react开发/生产环境

    一.初始化项目 在命令行中敲入如下命令: mkdir Webpack-react && cd Webpack-react && npm init -y 然后你就可以在你 ...

  2. (17/24) webpack实战技巧:生产环境和开发环境并行设置,实现来回切换

    (17/24) webpack实战技巧:生产环境和开发环境并行设置,实现来回切换 1. 概述 生产环境和开发环境所需依赖是不同: --开发依赖:就是开发中用到而发布时用不到的.在package.jso ...

  3. 查看webpack版本_webpack小结-生产环境构建优化

    刚刚对我们前端项目做了一顿分析优化操作,因为接手时每次构建要花两分钟左右的时间,实在忍受不了,只能动手了.通过这次优化,重新温习了下 webpack 的一些知识.接下来会关于 webpack 展开写几 ...

  4. webpack上线版(生产环境中推荐使用)

    配置上线版(生产环境)webpack: 实际中将开发环境中和生产环境中打包配置是分开的,两者本质没太大区别,只是生产环境中的webpack打包配置要更加优化合理,下面将具体介绍一下生产环境中webpa ...

  5. Vue + Spring Boot 项目实战(二十二):生产环境初步搭建

    重要链接: 「系列文章目录」 「项目源码(GitHub)」 本篇目录 前言 一.虚拟机与 CentOS 安装 二.MySQL 服务部署 1.虚拟机克隆及网络配置 2.MySQL 安装 3.MySQL ...

  6. 智能一代云平台(二十一):生产环境Nginx报 502 Bad Gateway 问题复现及解决方案

    强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan [前言] 系统最近出现了一个问题,经过相应的排查解决了:在此记录一下解决的整个过程,如果大家遇到 ...

  7. Centos 7 生产环境优化 Mysql 5.7

    目录 1.MySQL层相关优化 2.系统层相关优化 2.1其他内核参数优化 2.2文件系统层优化 3.硬件层相关优化 3.1CPU相关 3.2磁盘I/O相关 4.参考文章 假设生产服务器内存8核16G ...

  8. node代理请求 vue_vue-cli项目开发/生产环境代理实现跨域请求+webpack配置开发/生产环境的接口地址...

    使用 Vue-cli 创建的项目,开发地址是 localhost:8080,需要访问非本机上的接口http://10.1.0.34:8000/queryRole.不同域名之间的访问,需要跨域才能正确请 ...

  9. webpack开发环境和生产环境的配置区别

    1.定义: 开发环境:开发人员调试开发的一种环境: 方便调试,保持高效的开发 生产环境:发布上线的环境: 让程序在生产环境中正常有效的运行 开发环境的需求: 模块热更新 (本地开启服务,实时更新) s ...

最新文章

  1. python 利用多进程实现文件的拷贝
  2. 报表模板 — 在项目管理中应用数据报表分析
  3. 转:.Net 中的反射(反射特性) - Part.3
  4. 类与接口(二)java的四种内部类详解
  5. Task和async/await详解
  6. greenplum 查询出来的数字加减日期_Python实践代码总结第5集(日期相关处理)
  7. 专访刘伟:软件开发人员的内功修炼之道
  8. 校门外的树(洛谷-P1047)
  9. 【jQuery学习】—jQuery对象的过滤
  10. 吉林建筑大学电气与计算机学院院长,吉林建筑大学电气与计算机学院研究生导师:张玉红...
  11. 使用promise解决回调地狱_回调地狱的由来和如何利用promise解决回调地狱
  12. 尚硅谷RabbitMQ学习笔记(上)
  13. Copy-on-Write模式:写时复制
  14. Facebook自动化测试札记
  15. SAP License:SAP软件作用是什么
  16. 14. python-es-8.3.3-多词项聚合multi_terms
  17. 面试百问:如何提高自动化测试脚本稳定性
  18. 基于Andriod的连锁药店管理系统-计算机毕业设计源码+LW文档
  19. 电磁兼容入门篇之辐射发射(辐射骚扰)试验
  20. TIL: 申请一个30天的体验版本的 Salesforce Consumer Goods Cloud Org

热门文章

  1. php生成sn码,PHP 生成SN码
  2. NMS和Soft-NMS的原理和Pytorch代码实现
  3. 解决[FireDAC][DatS]-32. Variable length column [Name] overflow. Value length - [26], column maximum le
  4. MOOS-ivp 实验三 MOOS简介(2)
  5. office快速制作贺报方法
  6. numpy中linspace用法
  7. Java学习笔记_15 项目实战之天天酷跑(二):开始游戏界面
  8. 医学检验质量管理和控制计算机的,基层临床医学检验质量管理现状及其优化对策...
  9. 来自一个老码农的技术理想
  10. python的拼音_GitHub - mozillazg/python-pinyin: 汉字转拼音(pypinyin)