模块化这个话题在 ES6 之前是不存在的,因此这也被诟病为早期 JavaScript 开发全局污染和依赖管理混乱问题的源头。
常见的模块化方案包含这几种:
CommonJS
AMD
CMD
UMD
ES Modules
CommonJS 比 ES Modules 规范早了几年。 它旨在解决 JavaScript 生态系统中缺乏对可重用模块的支持。 CommonJS 有一个 require() 函数,它根据提供的路径获取外部模块,并在运行时将其添加到作用域中。
运行时执行的特点
从 CommonJS 规范中吸取教训,ES Modules 标准采用 import/export 关键字对模块进行处理,且不依赖运行时执行结果
执行 require 后内存产物
{ id: '...', exports: { ... }, loaded: true, ... }
CommonJS 的引用方式多种多样
const foo = require('foo'); function demo() { const foo = require('foo'); } if (statement) { const foo = require('foo'); } switch (key) { case value: const foo = require('foo'); break; default: break; } // ...
ES Modules 标准的特点
一个函数是不是“纯”的?
const pure = (a:number, b:number) => a + b const impure = (c:number) => window.foo.number + c
在 package.json 中标明
{ "name": "my-package", "sideEffects": false }
单独表明
var Button$1 = /*#__PURE__*/ withAppProvider()(Button);
{ "name": "your-project", "sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] }
在 webpack v4+ 开始
{ "mode": process.env.NODE_ENV === 'production' ? 'production' : 'development' }
在 webpack v3 及之前
// transform.js import * as mylib from 'mylib'; export const someVar = mylib.transform({ // ... }); export const someOtherVar = mylib.transform({ // ... }); // ------------------------------------------- // index.js import { someVar } from './transforms.js'; // Use `someVar`...
// before transformation import { Row, Grid as MyGrid } from 'react-bootstrap'; import { merge } from 'lodash'; // after transformation import Row from 'react-bootstrap/lib/Row'; import MyGrid from 'react-bootstrap/lib/Grid'; import merge from 'lodash/merge';
{ // ... "type": "module", "main": "./index-cjs.js", "module": "./index-esm.js", "exports": { "require": "./index-cjs.js", "import": "./index-esm.js" } // ... }