require/exports瀏覽器
CommonJS
、AMD
、CMD
等等。而Node
遵循CommonJS
規範,requireJS
遵循AMD
,seaJS
遵循CMD
。Node
沒法直接兼容ES6
語法,因此現階段require/exports
仍然是必要且是必須的。import/export緩存
babel
誕生後,它能將還未被宿主環境(各大瀏覽器、Node
)直接支持的ES6
語法編譯爲ES5
,也就是能將ES6 Module
的import/export
編譯爲CommonJS
的require/exports
這種寫法。/* 導出 */ exports.fs = fs; // 單個特性導出,可導出多個 module.exports = fs; // 整個模塊導出,每一個模塊只包含一個 /* 引入 */ const fs = require('fs'); // 引入整個模塊
/* 導出 */ export default fs; // 默認導出 每一個模塊包含一個 每次導出都會覆蓋前一個導出 export const fs; // 導出單個特性 每一個模塊包括多個 export function readFile; // 導出單個特性 每一個模塊包括多個 export { readFile, read }; // 導出列表 export * from 'fs'; // 導出模塊合集 /* 引入 */ import fs from 'fs'; // 引入整個模塊的內容 import '/fs.js'; // 僅爲反作用而引入一個模塊 不導入模塊中的任何接口 import * as fs from 'fs'; // 引入整個模塊的內容 import { readFile } from 'fs'; // 引入readFile單個接口 import { readFile as read } from 'fs'; // 引入模塊中read接口,並重命名爲readFile import fs , { readFile } from 'fs'; // 引入整個模塊的內容和readFile接口
require/exports
輸出的是一個值的拷貝,也就是說,當你引入一個值,模塊內部的變化是影響不到這個值的。babel
// test.js let num = 0; function addNum(){ num++; }; module.exports = { num: num, addNum: addNum } // main.js const test = require('./test.js'); console.log(test.num); // output: 0 test.addNum(); console.log(test.num); // output: 0
import/export
輸出的是值的索引,也就是說,該引用實際上是一個動態引用,並不會緩存值,當模塊內部發生變化,你的引入值也會隨之更新。異步
// test.js export let num = 0; export function addNum(){ num++; }; // main.js import { num, addNum } from './test.js'; console.log(num); // output: 0 addNum(); console.log(num); // output: 1
CommonJS
模塊是運行時加載。優化
由於CommonJS
模塊加載的是一個對象,即module.exports
屬性,該對象只有在腳本運行完才生成,也所以沒辦法再編譯時作「靜態優化」。ui
const { test1, test2, test3 } = require('test'); /* 等同於 */ const _test = require('test'); // 實質上加載了整個模塊,再從中讀取這三個方法 const test1 = _test.test1; const test2 = _test.test2; const test3 = _test.test3;
ES6
模塊是編譯時輸出接口。code
ES6
模塊不是對象,它對外接口只是一個靜態定義,在代碼靜態解析階段纔會生成,所以效率要比CommonJS
模塊加載高。對象
import { test1, test2, test3 } from 'test'; // 只從模塊中加載這三個方法,其餘的不加載
CommonJS
模塊中的require
是同步加載模塊。索引
ES6
模塊的import
命令是異步加載的,有一個獨立的模塊依賴的解析階段。接口