简单总结Commonjs 和 Es Module

62 阅读2分钟

传统模块化方式的问题

<body>
  <script src="./index.js"></script>
  <script src="./home.js"></script>
  <script src="./list.js"></script>
</body>

传统通过script标签引入模块的方式的问题:

  • 全局污染:没有块级作用域,会导致污染变全局量;
  • 依赖管理混乱:正常来说,引入的模块会被按引入顺序依次执行,模块间存在相互依赖的关系时,变得难以管理

Commonjs

使用:

导出:

// Commonjs到处相当于导出的是一个 exports 对象
exports.sex = 'male'
exports.name = 'Pike'
module.exports ={
    name:'alien', // 之前定义的name属性在这里被覆盖
    author:'青空',
    say(){
        console.log(666)
    }
}

导入:

const a = require('./a')

特性

  • CommonJS 模块由 JS 运行时实现。

  • CommonJs 是单个值导出,本质上导出的就是 exports 属性。

  • CommonJS 是可以动态加载的,对每一个加载完成的文件进行标记,进行缓存,当再次导入时无需重新加载,直接从缓存获取结果,可以有效的解决循环引用问题。

  • CommonJS 模块同步加载并执行模块文件,顺序执行,动态加载。

Es Module

使用

导出:

// Es Module导出一个对象,其中默认导出的内容存在default属性中,其余导出自动生成一个属性
export const name = 'Pike' // 在导出的对象中添加一个名为"name"的属性
export const author = '青空' // 同上

export default function say (){
    console.log('hello , world!')
} // 默认到处只能有一个,此时default属性即该函数

导入:

import theSay , // 默认导出需要命名
{ name, author as  bookAuthor } from './a.js'

重命名导出:

export { name as bookName ,  author , 
	default as say // 重命名默认导出的default
} from 'module' //第三种方式

特性

  • ES6 module 的引入和导出是静态的,因此 import , export 不能放在块级作用域或条件语句中,这有利于代码在打包过程中查找依赖,进行tree shaking

  • import 的导入名不能为字符串或在判断语句

  • import 会自动提升到代码的顶层,相当于定义变量,因此会提前加载,与Common.js相同,对于相同的js文件会进行标记及缓存

  • import 导入的变量时只读的,无法修改,相当于一个单例模式

  • import()方法动态引入,返回一个Promise 对象, 返回的 Promise 的 then 成功回调中,可以获取模块的加载成功信息。需要在 webpack 中做相应的配置处理才能支持这种方式。

    setTimeout(() => {
        const result  = import('./b')
        result.then(res=>{
            console.log(res)
        })
    }, 0);
    
  • ES6 Module 导入模块在严格模式下。