CommonJS

概述

CommonJS 是一个为了解决 Web 浏览器之外环境(如 Node.js)中模块生态系统而创建的项目。该项目由 Mozilla 工程师 Kevin Dangoor 于 2009 年 1 月开始,最初命名为 ServerJS。

What I’m describing here is not a technical problem. It’s a matter of people getting together and making a decision to step forward and start building up something bigger and cooler together. —Kevin Dangoor

2009 年 8 月,该项目更名为 CommonJS,以显示 API 的更广泛适用性。CommonJS与 Ecma International 小组 TC39 没有关联,致力于 ECMAScript,但 TC39 的一些成员参与了该项目。
2013 年 5 月,Node.js 的软件包管理器 npm 的作者 Isaac Z. Schlueter 表示,CommonJS正在被 Node.js 淘汰,并被核心 Node.js 开发人员所避免。
虽然如此,但是依旧有很多项目是遵循 CommonJS规范,所以我们依然需要去了解它。

CommonJS 介绍

CommonJS规范中,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。模块必须通过 module.exports 导出对外的变量或接口,通过require()来导入其他模块的输出到当前模块作用域中。

模块导出

  1. // num.js
  2. var num = 5;
  3. var addNum = function(value) {
  4. return value + num;
  5. };
  6. // 通过 module.exports 的语法导出 addNum 函数
  7. module.exports.addNum = addNum;

模块导入

// index.js
// 通过 require 的语法来导入 num 模块
var num = require("./num.js");
console.log(num.addNum(1)); // 6

路径映射

image.png
相对路径按顺序查找
image.png
非相对路径查找策略(如React)
image.pngimage.png

答案

A B

解析

ts 提供了两种模块解析策略

  • Node
  • Classic

ts 提供了两种模块导入方式

  • 相对模块导入
  • 非相对模块导入

相对模块导入方式如:

  • import { animal } from ‘./animal’

非相对模块导入方式如:

  • import { animal } from ‘animal’

// 文件路径 /root/page/index.ts import { animal } from “animal”;
对于题目中的代码块,解析策略为:

  • /root/page/node_modules/animal.js
  • /root/page/node_modules/animal/package.json(如果指定了”main”属性)
  • /root/page/node_modules/animal/index.js
  • /root/node_modules/animal.js
  • /root/node_modules/animal/package.json(如果指定了”main”属性)
  • /root/node_modules/animal/index.js
  • /node_modules/animal.js
  • /node_modules/animal/package.json(如果指定了”main”属性)
  • /node_modules/animal/index.js

所以正确答案为 A B。

动态 import

/* 动态 import */
// 传统的import 打包时合并为一个文件,无法按需加载
import sum from './sum'
document.getElementById('button').addEventListener('click', () => {
    alert(sum(1,2))
})


// 需要同时修改 tsconfig.json的module: 'esnext' 才支持这种语法 即一代的模块系统
// 动态的import() 动态的导入JS文件 写法1
document.getElementById('button').addEventListener('click', () => {
    import('./sum').then(module => {
        alert(module.default(1,2))  // 默认是default
    }
})

// 动态的import() 动态的导入JS文件 写法2
// webpack 独有语法,将打包的文件以指定的名字进行文件命名如 sum.bundle.js
document.getElementById('button').addEventListener('click', async () => {
    const sum = await import(/* webpackChunckName: "sum" */ './sum')
    alert(sum.default(1, 2))
})

image.png

答案

A B

解析

动态 import 结合 webpack 可以实现按需加载,实现性能优化。
在 ts 中使用动态 import 需要配置

// tsconfig.json
{
  "compilerOptions": {
    // 或者 "module": "commonjs",
    "module": "esnext",
    ...
  },
}

题目中提供了两种动态 import 的方式。是正确的。