[前端面试] CommonJs与ES Module的区别、Tree Shaking

一、CommonJs

导出

  • module.exports
module.exports={
	name:’zs’,
	age:18
}

module.exports.sex = null

  • exports (省略module,直接导出)
exports.name = "蛙人"
exports.sex = "male"

导入

  • require
// index.js
module.exports.name = "蛙人"
module.exports.age = 24

let data = require("./index.js")
console.log(data) // { name: "蛙人", age: 24 }

二、ES Module

导出

  • export (单个导出)
  • export default(默认导出)

导入

  • imort (只能放在文件顶部,不能动态加载语句)
// index.js

import {isEmpty as isObjectEmpty } from ../utils’
import {CONSTANTS as PROJECT_CONSTANTS, BAAS} from ../config’

export const PROJECT_CONFIG = {
	…PROJECT_CONSTANTS,
	FUNCTION: BAAS.CLOUD_FUNCTION
}

三、CommonJs和Es Module的区别

CommonJs

  • CommonJS 模块是 Node.js 专用的,与 ES6 模块不兼容。

  • CommonJS 模块使用 require()和 module.exports

  • CommonJs 可以动态 require 加载语句,代码发生在运行时

  • CommonJs 混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了

  • CommonJs 导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染

Es Module

  • ES6模块化在浏览器和 node.js 中都可以用

  • ES6 模块使用 import 和 export

  • Es Module 是静态的,不可以动态加载语句,只能声明在该文件的最顶部,代码发生在编译时

  • Es Module 混合导出,单个导出,默认导出,完全互不影响

  • Es Module 导出是引用值之前都存在映射关系,并且值都是可读的,不能修改

在 node.js 使用模块化,需要将 CommonJS 脚本的后缀名都改成 .cjs ,ES6 模块采用 .mjs 后缀文件名。

或者修改 package.son 里面的文件,type 字段为 module 或 commonjs。

四、Tree Shaking

前端中的 Tree-shaking 可以理解为通过工具"摇"我们的JS文件,将其中用不到的代码"摇"掉,是一个性能优化的范畴。

具体来说,在 webpack 项目中,有一个入口文件,相当于一棵树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 Tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。

开发环境:webpack.config.js 文件中添加 optimization 选项。
生产模式:不用配置下面的属性(默认)

optimization: PROD
? {
    runtimeChunk: 'single',
    chunkIds: 'deterministic',
    moduleIds: 'deterministic',
    minimizer: [
      new TerserPlugin(terserPluginConfig),
      new CssMinimizerPlugin({test: /\.css$/}),
    ],
    splitChunks: splitChunksConfig,
  }
: undefined,

package.json文件中添加 sideEffects 选项

 "sideEffects": false,  //对所有的模块都进行Tree Shaking
如果需要对某个模块不进行Tree Shaking

 "sideEffects": ["@babel/poly-fill"],  //该模块不进行Tree Shaking

为什么某些引入模块不希望进行Tree Shaking呢?

下面引入的style.css模块,如果也使用Tree shaking,由于css文件没有导出任何模块,那么就有可能在打包的时候该引入模块就被摇晃掉了,导致bug。

在 package.json 中进行配置,即匹配到的任何css文件都不进行Tree Shaking

{
	"name":"lesson", 
	"sideEffects":[*.css]
}

Tree-Shaking性能优化实践 - 原理篇

Tree Shaking只支持ES模块的使用,不支持require这种动态引入模块的方式。而ESM的 import 引入是静态引入,commonjs 的require引入 是动态引入。

ES6 module 特点:只能作为模块顶层的语句出现import 的模块名只能是字符串常量import binding 是 immutable的ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这就是tree-shaking的基础。

所谓静态分析就是不执行代码,从字面量上对代码进行分析,ES6之前的模块化,比如我们可以动态require一个模块,只有执行后才知道引用的什么模块,这个就不能通过静态分析去做优化。

这是 ES6 modules 在设计时的一个重要考量,也是为什么没有直接采用 CommonJS,正是基于这个基础上,才使得 tree-shaking 成为可能,这也是为什么 rollup 和 webpack 2 都要用 ES6 module syntax 才能 tree-shaking。

作者:百度外卖大前端技术团
链接:https://juejin.cn/post/6844903544756109319
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值