模块加载方案
先来总结一下不同的模块加载方案:
- CommonJS (Node.js)
CommonJS 是 Node.js 中使用的模块加载方案。它使用 require() 函数来引入模块,使用模块上的 exports 对象导出代码。这种方式是同步的,每个模块在首次加载之后会被缓存,之后再次引用时就可以直接使用缓存,不需要重新加载。
示例:
javascript复制
// 加载模块
const MyModule = require('my-module.js');
// 导出代码
module.exports = { foo: 'bar' };
另外,要说明的是,CommonJS规范是一种通用的模块化规范,与Node.js的模块系统紧密相连,但是它们并不是完全相同的东西。
Node.js 的模块系统是基于 CommonJS 模块规范的一个实现,支持使用 require() 加载模块,使用 module.exports 和 exports 导出模块。在 Node.js 环境下,CommonJS 模块是可以直接使用的,因为 Node.js 已经内置了 CommonJS 的实现。
但是,对于在 Web 浏览器中运行的 JavaScript 应用程序,不同的浏览器可能实现有所不同,不一定支持 CommonJS 模块规范。因此在这种情况下,如果需要在浏览器环境中模块化开发,可能需要使用其他的模块规范或者通过打包工具进行转换。
Node.js 的模块系统实现了 CommonJS 规范并在 Node.js 中内置,但是不同于 CommonJS 规范的通用实现,因此在浏览器环境下不能直接使用 CommonJS 模块。如果希望在浏览器环境下使用 CommonJS 模块,则需要使用特定的工具(如 Browserify)将其转换为适合在浏览器中运行的代码。 在Node.js版本8和更高版本中,Node.js引入了ES6的模块化规范,允许使用import和export来进行模块的导入和导出。ES6的模块规范和之前的CommonJS规范还是稍有不同的,ES6模块不是基于文件系统,静态引入模块,而是更加底层,具有静态分析的能力。
Node.js的作者认识到了ES6 Modules规范的强大,并在Node.js中支持它。这样,Node.js通过支持ES6模块规范,使得Node.js环境下,实现了既能够在前端实现,又能够在后端实现的模块化方案。但是,需要注意的是,使用import语句需要在文件扩展名.mjs的文件扩展名或在package.json中进行相关的配置。
- AMD (require.js)
AMD (Asynchronous Module Definition) 是用于浏览器环境的模块加载方案,主要通过 RequireJS 进行实现。它支持异步加载,可以在运行时动态地加载依赖的模块。使用 AMD 的模块通过 define() 函数定义,可以通过 require() 函数来引入依赖的模块。
RequireJS 和 require的不同
- require 是 Node.js 自带的一个模块化加载器,可用于在 Node.js 中加载模块,它主要用于 CommonJS 规范的模块化开发。而 RequireJS 是一个 JavaScript 模块加载器,主要用于浏览器端的模块化开发。RequireJS 支持加载 AMD 风格的模块。
- 加载方式不同:require 是同步加载模块,而 RequireJS 是异步加载模块。
- 模块化规范不同:require 遵循 CommonJS 规范,而 RequireJS 遵循 AMD 规范。
- 适用范围不同:require 更适合在服务器端或命令行环境中使用,而 RequireJS 更适合在浏览器端使用。
示例:
javascript复制
// 定义模块并导出代码
define(['jquery'], function($) {
var foo = 'bar';
return {foo: foo};
});
// 加载模块并使用
require(['path/to/module'], function(module) {
console.log(module.foo);
});
- ES6 模块 (JavaScript)
ES6 模块是 ECMAScript 6 标准中定义的模块加载方案。使用 ES6 模块可以将代码划分为小的模块,通过 export 和 import 关键字导出和引入模块代码。ES6 模块是静态加载的,可以进行静态分析和优化,可以在开发时进行更强的类型检查。
示例:
javascript复制
// 导出代码
export const foo = 'bar';
// 加载模块并使用
import { foo } from 'path/to/module';
console.log(foo);
- UMD (Universal Module Definition)
UMD 可以将模块兼容 CommonJS 和 AMD 两种规范的加载方式,还可以支持全局引用。通过判断是否存在 define 和 module.exports 等特定的变量来决定加载方式。当模块被加载时,将根据当前环境自动选择使用 CommonJS、AMD 或全局变量等方式导出和使用模块。
示例:
javascript复制
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('jquery'));
} else {
// 浏览器全局变量
root.myModule = factory(root.jQuery);
}
}(this, function($) {
// 模块代码
}));
- SystemJS
SystemJS 是一个支持 ES6、AMD、CommonJS 和全局模块等多种模块加载方式的加载器。可以在浏览器和 Node.js 环境中使用。
示例:
javascript复制
// 加载模块
System.import('path/to/module').then(function(module) {
console.log(module.foo);
});
// 导出代码
System.register([], function(exports, module) {
var foo = 'bar';
exports({foo: foo});
});
以上就是常见的几种模块加载方式和使用方法的简单介绍和示例代码。
rollup 配置项(注释写得老清楚了)
// 压缩
import { terser } from 'rollup-plugin-terser';
// 将 Node.js (node 内置的 require)模块转换为 ES6 (import)模块,rollup 默认没有
import resolve from '@rollup/plugin-node-resolve';
// 对于在 Web 浏览器中运行的 JavaScript 应用程序,不同的浏览器可能实现有所不同,不一定支持 CommonJS 模块规范。因此在这种情况下,如果需要在浏览器环境中模块化开发,可能需要使用其他的模块规范或者通过打包工具进行转换。
import commonjs from '@rollup/plugin-commonjs';
// 浏览器中没有process变量,这种node变量需要直接替换为字符串变量
import replace from '@rollup/plugin-replace';
// 用于解析一些新的语法,将新语法转换成es5语法
import babel from '@rollup/plugin-babel';
// 用于解析 ts
import typescript from 'rollup-plugin-typescript2';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
export default {
input: 'index.ts',
output: {
file: 'dist/ProTable.umd.js',
format: 'umd',
name: 'ProComponents',
// 将sourcemap 打包进umd.js里面
sourcemap: 'inline',
// 外部引用的,挂在window上的变量名字
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'react-router-dom': 'ReactRouterDom',
},
},
plugins: [
resolve({ extensions }),
replace({
values: {
'process.env.NODE_ENV': JSON.stringify('development'),
},
preventAssignment: true,
}),
commonjs(),
typescript({ useTsconfigDeclarationDir: true }),
babel({
extensions,
babelHelpers: 'runtime',
exclude: 'node_modules/**',
presets: [
'@babel/preset-react', // 添加这一行
['@babel/preset-env', { modules: false }],
'@babel/preset-typescript',
],
plugins: ['@babel/plugin-transform-runtime', '@babel/proposal-class-properties'],
}),
],
// 不希望打包到umd的外部引用,既然没有打包就需要在globals里面告知外部引用的变量名字
external: ['react', 'react-dom', 'react-router-dom'],
};