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


  • 2018-11-17 21:05:48

    Android ANR发生的原因总结和解决办法

    ANR的全称是application not responding,是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。

  • 2018-11-17 21:08:09

    Android 单个应用的内存限制

    获取Android手机应用内存大小 手机不同其性能也不同,手机本身内存可能有大有小,所以针对每个应用的内存大小也不相同。

  • 2018-11-17 21:11:14

    Android中App可分配内存的大小

     结果:(1)未设定属性android:largeheap = "true"时,可以申请到的最大内存空间为221M。      (2)设定属性android:largeheap = "true"时, 可以申请的最大内存空间为478M,是原来的两倍多一些。

  • 2018-11-17 22:44:53

    LeakCanary,30分钟从入门到精通

    在性能优化中,内存是一个不得不聊的话题;然而内存泄漏,显示已经成为内存优化的一个重量级的方向。当前流行的内存泄漏分析工具中,不得不提的就是LeakCanary框架;这是一个集成方便, 使用便捷,配置超级简单的框架,实现的功能却是极为强大的。

  • 2018-11-17 22:53:01

    gc for alloc freed

    在数组中选择图片然后显示,然后。。。logcat不断显示GC回收。最后程序黑屏。

  • 2018-11-17 23:25:38

    Android高效内存1:一张图片占用多少内存

    在做内存优化的时候,我们发现除了解决内存泄露问题,剩下的就只有想办法减少真实的内存占用。而在App中,大部分内存可能被我们图片占用了,所以减少图片的内存占用可以带来直接的效果。本文就简单介绍一张图片到底占用多少内存,我们先假设我们有一张图片时 600 * 800 的,图片占用空间大小假设是 100KB。另外本文知识点也是面试官喜欢问的一个点,看看自己的回答到什么级别了。

  • 2018-11-18 09:06:06

    Android子线程中更新UI的3种方法

    UI的更新必须在主线程中完成,所以不管上述那种方法,都是将更新UI的消息发送到了主线程的消息对象,让主线程做处理。

  • 2018-11-19 15:10:23

    nodemailer的使用,nodejs发送邮件

    前段时间有个很普通的项目需要发邮件的功能,而且是刚开始学nodejs,所以只是搜索了下用什么好的库能实现,就找到了nodemailer了。这篇文章主要是记录一下使用的过程和经验。