Tree Shaking我原来也只是了解,这次碰巧深入研究了下,就写个博客记录一下,网上有很多讲Tree Shaking的,我写的这篇跟他们侧重点不一样

Tree Shaking相关的基础知识

1 webpack会从入口文件开始不断的获取你的依赖,就像一颗树一样从根节点开始不断往下延伸,只有被依赖的文件才会加入树,注意这不叫Tree Shaking,Tree Shaking是指依赖的文件只需要的一部分,则把不需要的部分代码摇掉

2 Tree Shaking只能识别es6语法,这点很关键(注意去掉polyfill的模块降级),但是webpack不支持es6打包,也就是说你用import写的代码可以被Tree Shaking,但是你npm别人的库,如果别人不是es写法,那么无法Tree Shaking。比如lodash和lodash-es,后者是es的导入写法,代码就可以被压缩。

3 Tree Shaking原来是用uglifyjs来做压缩的,现在由于现在不维护uglify-es了(uglify-es is no longer maintained ),现在改用terser了,据说是uglify的一个分支。(对我们使用来说其实没什么感觉,只是了解一下)

4 什么是副作用,之前看别人的文章看到懵懵的,后面终于理解了,其实很简单

index.js 如下,就是导入了util.js

import './vendor/util'

vendor/util.js 如下,里面有做全局的修改或者console.log什么东西,我这里就是给全局的window加了个属性a,没有导出东西来,却使用了这个js文件,这就是副作用

// vendor/util.js
export function a() {
return 'this is function "a"';
} export function b() {
return 'this is function "b"';
} export function c() {
return 'this is function "c"';
}
window.a = 43

有时候我们写代码用这种写法,由于里面没有导入东西进来,webpack准确说是terser就不知道你到底要不要这个东西,万一里面有修改全局的操作你把它丢了肯定不行,如果不丢那你就要去读一遍文件才知道到底有没有副作用,官方文档说是非常耗时且因为js是动态语言所以是非常不可靠的操作,我这里仅仅是写的非常简单,工作中可能业务变得更加复杂。

Tree Shaking的基础了解完了,接下来讲下我读webpack文档的一些见解

先发2篇我读过的关于Tree Shaking较好的文章

webpack官网讲解Tree Shaking的文档:https://webpack.js.org/guides/tree-shaking/#root

你的Tree-Shaking并没什么卵用:https://segmentfault.com/a/1190000012794598

根据‘你的Tree-Shaking并没什么卵用’ 这篇文章说UglifyJS完全不能识别副作用,但是我自己做了一些测试发现,目前的webpack4.40.2是可以识别大部分副作用的。

然后讲下官网的文档,之前说了terser识别副作用特别的耗时且不准确(官方举例是react的hoc无法识别副作用),如果你能指定你的哪些文件有副作用或者所有文件都没有副作用那就皆大欢喜了,于是在package.json里出了一个属性sideEffects

接下来我做了一些测试关于sideEffects属性,注意terser的Tree Shaking只在生产环境webpack会给你调用来压缩代码,dev是不会压缩代码自然不会Tree Shaking的

第一种情况,index和util都不变,sideEffects:false,指定所有的文件都没有副作用

结果是terser完全不去管你这个文件里面写的啥,就是说你给window加个属性a没有执行

第二种情况,index和util都不变,sideEffects:["./src/vendor/util.js"],指定util是有副作用

结果terser读了util,知道了你做了什么处理,于是window加个属性a成功执行

第三种情况,index和util都不变,不加sideEffects,不告诉terser哪些有副作用,叫它自己每个引用了的文件都去看下代码

结果terser读了util,知道了你做了什么处理,于是window加个属性a成功执行

第四种情况,index变成如下代码

import { a } from './vendor/util'

结果和index使用import './vendor/util'的每种情况一样,也就是说你导入了a但是没有使用,在terser看来就是import './vendor/util'差不多

第五种情况

index变成如下代码

import { a } from './vendor/util'
console.log(a())

结果无论sideEffects怎么设置,window加个属性a都会成功

通过几次测试下来发现sideEffects属性只是针对你从文件导入了方法却没有使用(或者你压根没有导入方法)的情况生效,从这么看来sideEffects属性其实能做的优化不大,而且只是针对打包速度方面的优化(包已经打好了,访问速度跟它没有关系了),而且很坑,一个前端项目如果不只你一个人参与,你偷偷加个sideEffects属性,然后代码没压缩在dev跑的好好的,放到生产环境突然就失效了,假设人家不知道sideEffects,那抓破脑袋也不知道是咋回事(如果你就是想坑你同事,那你就可以happy了~)

深入研究webpack之Tree Shaking相关属性sideEffects用处的更多相关文章

  1. Webpack 4 Tree Shaking 终极优化指南

    几个月前,我的任务是将我们组的 Vue.js 项目构建配置升级到 Webpack 4.我们的主要目标之一是利用 tree-shaking 的优势,即 Webpack 去掉了实际上并没有使用的代码来减少 ...

  2. webpack使用tree shaking的问题。及关于UglifyJs不支持ES6的解决方案。

    webpack: plugins:[ new webpack.optimize.UglifyJsPlugin({ compress:{warning:true} }) ] 是的,一些dead code ...

  3. [Webpack 2] Tree shaking with Webpack 2

    The less code you can send to the browser, the better. The concept of tree shaking basically says th ...

  4. Webpack 的 Tree Shaking

    为什么要使用 Tree Shaking? 当从某文件模块中导出(某一个或几个变量.函数.对象等),然而这个文件模块还有许多其它(我们这次并不需要)的导出,webpack会不管三七二十一简单粗暴的将整个 ...

  5. webpack和tree shaking和rollup

    http://blog.csdn.net/haodawang/article/details/77199980 tree shaking只对es模块生效,在打包tyscript模块是要使用tsc编译器 ...

  6. Webpack 4教程 - 第七部分 减少打包体积与Tree Shaking

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/08/13/webpack-4-course-part ...

  7. webpack(6)-模块热替代&tree shaking

    模块热替换(hot module replacement 或 HMR) 模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一.它允许在运行时 ...

  8. 配置Tree Shaking来减少JavaScript的打包体积

    译者按: 用Tree Shaking技术来减少JavaScript的Payload大小 原文: Reduce JavaScript Payloads with Tree Shaking 译者: Fun ...

  9. Webpack 中的 Tree Shaking

    Tree Shaking Tree shaking 用于描述移除JavaScript上下文中的未引用代码(dead-code). 为了更方便地理解tree shaking,我们可以将应用程序想象成一棵 ...

随机推荐

  1. 【连载】微服务网格Istio(一)

    Istio基础 服务网格是用于描述构成应用程序的微服务网络以及应用之间的交互,服务网格的功能包括服务发现.负载均衡.故障恢复.指标和监控以及更加复杂的运维工作,例如A/B测试.金丝雀发布.限流.访问控 ...

  2. SpringBoot读取Resource下文件的几种方式(十五)

    需求:提供接口下载resources目录下的模板文件,(或者读取resources下的文件)给后续批量导入数据提供模板文件. 方式一:ClassPathResource //获取模板文件:注意此处需要 ...

  3. java String转List<Device>集合

    // 从Redis中获得正常设备的数量 String success = redisService.get(RedisKey.CULTIVATION_RECORD_SUCCESS); //建立一个li ...

  4. [考试总结]noip模拟17

    爆零了! 菜爆了 弱展了 垃爆了 没有什么可以掩饰你的菜了 这次考试为我带来了第一个 \(\color{red}{ \huge{0}}\) 分,十分欣慰.... 最近的暴力都打不对,你还想什么正解?? ...

  5. Django中ORM是啥?

    ORM是啥是许多Django新手的苦恼. ORM中的"O"就是object,也就是我们说的对象:R指的是relations关系:M指的是mapping也就是映射.所以ORM是对象- ...

  6. JS 高级程序设计3.5.1一元操作符 递增和递减操作符++ --

    var age =29 ++age; 在这个例子中,前置递增操作符把age的值变成了30.实际上,执行这个前置递增操作符与执行 一下操作的效果相同: var age=29; age =age+1;// ...

  7. 文件上传靶机DVWA和upload-labs

    DVWA靶机 LOW <?php phpinfo() ?> 上传文件 Medium级别 修改Content-Type: application/octet-stream的值为jpg的格式为 ...

  8. 必备!一文掌握Wordpress插件

    必备!一文掌握Wordpress插件 什么是插件? Wordpress是一个非常强大的建站系统,而在我们建站的过程中,插件的使用必不可少. 插件是WordPress功能的扩展,也是WordPress得 ...

  9. Git 修改历史 commits 中的用户名和邮箱

    一.作用 修改某个仓库历史 commit 的用户 name 和 email 信息. 将历史提交记录中的指定 name/email 修改为新的 name/email. 二.步骤 确认本地全局邮箱/用户名 ...

  10. Java程序设计(2021春)——第四章接口与多态笔记与思考

    Java程序设计(2021春)--第四章接口与多态笔记与思考 本章概览: 4.1 接口(接口的概念和声明接口.实现接口的语法) 4.2 类型转换 4.3 多态的概念 4.4 多态的应用 4.5 构造方 ...