CommonJs 与 ESModule区别

2021-01-08 16:49:59

参考地址 CommonJs 与 ESModule区别

CommonJs(Node)
  • 模块运行时动态加载

node中模块导入require是一个内置的函数,因此只有在运行后我们才可以得知模块导出内容,无法做静态分析

1
2
const fileName = 'xx.js';
const xx = require(fileName);

  • 默认未开启严格模式

1
2
3
4
5
console.log(this); 
function (){
   console.log(this);// 指向global
}
name();

node中未开启严格模式情况下全局this指向module.exports。

ESModule
  • 默认开启严格模式(‘use strict’)

1
2
3
4
5
console.log(this);// undefined
function (){
   console.log(this);// undefined
}
name();

  • 静态解析

    • 只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面

    • import 的模块名只能是字符串常量

    • import 声明提前,在模块顶层

Tree Shaking

利用ES2015(es6)模块语法静态解析的特性,删除没有使用的代码,减小文件大小,对代码进行优化。
webpack 2.0 加入了这一特性。

源码

1
2
3
4
5
6
//export.js
export function a1(){alert('a1')};
export function a2(){alert('a2')};
//import.js
import {a1} from './export.js'
a1('arguments')

压缩后
  • 关闭tree shaking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
!function (modules) {
   function __webpack_require__(moduleId) {
       // ...some code
   }
   var installedModules = {};
   // ...some code
}([
   function (module, exports, __webpack_require__) {
;
       (0, __webpack_require__(1).a1)("arguements")
   },
   function (module, exports, __webpack_require__) {
;
       Object.defineProperty(exports, "__esModule", {
           value: !0
       }),
       exports.a1 = function () {
           alert("!")
       },
       exports.a2 = function () {
           alert("!!")
       }
   }
]);

  • 开启tree shaking

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
!function (modules) {
   function __webpack_require__(moduleId) {
       // ...some code
   }
   var installedModules = {};
   // ...some code
}([
   function (module, __webpack_exports__, __webpack_require__) {
;
       Object.defineProperty(__webpack_exports__, "__esModule", {
           value: !0
       });
       var __WEBPACK_IMPORTED_MODULE_0__es6_export__ = __webpack_require__(1);
       Object(__WEBPACK_IMPORTED_MODULE_0__es6_export__.a)("arguements")
   },
   function (module, __webpack_exports__, __webpack_require__) {
;
       __webpack_exports__.a = function () {
           alert("!")
       }
   }
]);

webpack Tree Shaking 开启条件:
  • 使用es2015模块语法(import 与 export)

  • 使用支持无用代码移除(dead code removal)的插件,如 UglifyJSPlugin

  • 去除babel-loder的模块转换插件,交给webpack来做模块转换babel 6.0+ 配置

不足:
  • npm公共包大多不支持es2015 module

  • 与babel兼容做的不好,待babel重启modules属性

结论
  • 浏览器端代码使用es2015 module,模块化使用灵活,且可充分利用Tree Shaking减小代码体积

  • 服务端node适合动态引入且不需要过多考虑代码体积所以使用commonjs规范,同时可以拥有更好的debug支持,提高开发效率

Tips
  • webpack内置uglifyPlugin版本相对较低,建议不使用内置版本,单独安装

  • babel6以下版本只需设置参数modules为false即可,babel6及以上只能列出除去transform-es2015-modules-commonjs所有plugin

  • 建议只import需要的方法,而不是import整个模块,便于去除dead_code


  • 2020-04-08 22:46:28

    Element的操作方法

    Element 是一个通用性非常强的基类,所有 Document 对象下的对象都继承自它。这个接口描述了所有相同种类的元素所普遍具有的方法和属性。一些接口继承自 Element 并且增加了一些额外功能的接口描述了具体的行为。例如, HTMLElement 接口是所有 HTML 元素的基本接口,而 SVGElement 接口是所有 SVG 元素的基础。大多数功能是在这个类的更深层级(hierarchy)的接口中被进一步制定的。

  • 2020-04-12 17:42:43

    Node.js设置CORS跨域请求中多域名白名单的方法

    在Node.js中,res的响应头Header中的 Access-Control-Allow-Origin 属性不能匹配除 (*) 以外的正则表达式的,域名之间不能也用逗号分隔。也就是说, Access-Control-Allow-Origin 的属性值只允许设置为单个确定域名字符串或者 (*)。

  • 2020-04-14 09:40:59

    CSS3实现文字描边的2种方法

    首先想到去看CSS3有没有什么属性可以实现,后来被我找到了text-stroke     该属性是一个复合属性,可以设置文字宽度和文字描边颜色      该属性使用很简单:text-stroke:1px #f00;(1px是文字宽度,#ff是文字描边颜色)

  • 2020-04-14 09:42:47

    用 TypeScript 编写 npm 模块

    自从开始使用 Node.js 已经一年多,写的代码越多,越是觉得自己提高的越慢。想来应该有没有将单一功能的代码封装在一个独立模块,而导致代码稍微多一点就维护困难的原因。

  • 2020-04-14 09:46:25

    TypeScript 入门教程

    TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。

  • 2020-04-14 09:51:03

    package.json 字段说明

    package.json 有很多字段,也有很多官方字段,我们需要知道他们的具体是做什么的才能很好的运用