今天这道题目是在和小红书的一位面试官聊的时候:前端
我:若是要你选择一道题目来考察面试者,你最有可能选择哪一道?webpack
面试官:那应该就是介绍一下tree shaking
及其工做原理?es6
我:为何?web
面试官:是由于最近面了好多同窗,你们都说熟悉webpack
,在项目中如何去使用、如何去优化,也都或多或少会提到tree shaking
,可是每当我深刻去问其工做机制或者原理时,却少有人能回答上来。(小声 bb:并非我想内卷,确实是工程师的基本素养啊,哈哈 😄)面试
面试官:那你来回答一下这个问题?浏览器
我:我也用过tree shaking
,只是知道它的别名叫树摇
,最先是由Rollup
实现,是一种采用删除不须要的额外代码的方式优化代码体积
的技术。可是关于它的原理,我还真的不知道,额,,,,服务器
咱们平时更多时候是停留在应用层面,这种只是能知足基础的业务诉求,对于后期的技术深挖以及我的的职业发展都是受限的。仍是那句老话:知其然,更要知其因此然~
话很少说,下面我就带你们一块儿来深刻探究这个问题。post
Tree shaking
Tree shaking
是一种经过清除多余代码方式来优化项目打包体积的技术,专业术语叫Dead code elimination
这个概念,我相信大多数同窗都是了解的。什么,你不懂?学习
不懂不要紧,我能够教你啊(不过那是另外的价钱,哈哈 🙈)优化
走远了,兄弟,让咱们言归正传:tree shaking
如何工做的呢?
tree shaking
如何工做的呢?虽然 tree shaking
的概念在 1990 就提出了,但直到 ES6
的 ES6-style
模块出现后才真正被利用起来。
在ES6
之前,咱们可使用CommonJS
引入模块:require()
,这种引入是动态的,也意味着咱们能够基于条件来导入须要的代码:
let dynamicModule; // 动态导入 if (condition) { myDynamicModule = require("foo"); } else { myDynamicModule = require("bar"); }
可是CommonJS
规范没法肯定在实际运行前须要或者不须要某些模块,因此CommonJS
不适合tree-shaking
机制。在 ES6
中,引入了彻底静态的导入语法:import
。这也意味着下面的导入是不可行的:
// 不可行,ES6 的import是彻底静态的 if (condition) { myDynamicModule = require("foo"); } else { myDynamicModule = require("bar"); }
咱们只能经过导入全部的包后再进行条件获取。以下:
import foo from "foo"; import bar from "bar"; if (condition) { // foo.xxxx } else { // bar.xxx }
ES6
的import
语法能够完美使用tree shaking
,由于能够在代码不运行的状况下就能分析出不须要的代码。
看完上面的分析,你可能仍是有点懵,这里我简单作下总结:由于tree shaking
只能在静态modules
下工做。ECMAScript 6
模块加载是静态的,所以整个依赖树能够被静态地推导出解析语法树。因此在 ES6
中使用 tree shaking
是很是容易的。
tree shaking
的原理是什么?看完上面的分析,相信这里你能够很容易的得出题目的答案了:
ES6 Module
引入进行静态分析,故而编译的时候正确判断到底加载了那些模块但到这里,本篇文章还没结束。从这道题目咱们能够很容易的引伸出来另一道“明星”面试题:common.js 和 es6 中模块引入的区别?
这道题目来自冴羽
大佬的阿里前端攻城狮们写了一份前端面试题答案,请查收
这里就直接贴下他给出的答案了:
CommonJS
是一种模块规范,最初被应用于 Nodejs
,成为 Nodejs
的模块规范。运行在浏览器端的 JavaScript
因为也缺乏相似的规范,在 ES6
出来以前,前端也实现了一套相同的模块规范 (例如: AMD
),用来对前端模块进行管理。自 ES6
起,引入了一套新的 ES6 Module
规范,在语言标准的层面上实现了模块功能,并且实现得至关简单,有望成为浏览器和服务器通用的模块解决方案。但目前浏览器对 ES6 Module
兼容还不太好,咱们平时在 Webpack
中使用的 export
和 import
,会通过 Babel
转换为 CommonJS
规范。在使用上的差异主要有:
一、CommonJS
模块输出的是一个值的拷贝,ES6
模块输出的是值的引用。
二、CommonJS
模块是运行时加载,ES6
模块是编译时输出接口。
三、CommonJs
是单个值导出,ES6 Module
能够导出多个
四、CommonJs
是动态语法能够写在判断里,ES6 Module
静态语法只能写在顶层
五、CommonJs
的 this
是当前模块,ES6 Module
的 this
是 undefined
冴羽
大佬的文章质量都很是高,也欢迎你们多去支持冴羽
大佬,相信看完必定会对你有所收获。
这是大厂面试问题解析
的第二篇了,和以前准备写这一系列的初衷同样:我力求经过一些面试题去发掘本身不曾了解或者不曾深刻了解的一个领域。
面试题更多时候是一个引子,更可能是想经过面试题去思考题目背后带来的对某一模块的深刻学习和探讨。
固然,每篇文章也不会只是草草给出答案,我都会尽可能深刻浅出的给出本身对于这道题目的理解,也会在这个基础上作一些拓展。