主要學習一下四種模塊加載規範:javascript
前端模塊化開發那點歷史html
requirejs 爲全局添加了 define 函數,你只要按照這種約定的方式書寫這個模塊便可。前端
define(function () { //Do setup work here return { color: "black", size: "unisize" } });
//my/shirt.js now has some dependencies, a cart and inventory //module in the same directory as shirt.js define(["./cart", "./inventory"], function(cart, inventory) { //return an object to define the "my/shirt" module. return { color: "blue", size: "large", addToCart: function() { inventory.decrement(this); cart.add(this); } } } );
以上示例代碼來源於require.js官網java
demo代碼詳見 https://github.com/BillyQin/jsModule/tree/master/requireJsnode
require.js 爲全局添加了define 函數,按照這種約定方式寫便可。webpack
這個約定方式就是AMD(The Asyncchronous Module Definition)git
因此AMD規範就是定義了怎麼寫define函數。只要按照這個規範來寫模塊和依賴,require.js就能正確解析。es6
demo代碼詳見 https://github.com/BillyQin/jsModule/tree/master/seaJsgithub
一樣的道理,CMD就是Sea.js對模塊定義對規範化產出。web
因此CMD的內容就是描述該如何定義模塊,如何引入模塊,如何導出模塊。只要按照這個規範來寫模塊和依賴,sea.js就能正確解析。
CMD推崇依賴就近
AMD 和 CMD 都是用於瀏覽器的模塊規範,而在服務端(node),則採用CommonJS。
CommonJS和sea.js同樣,require的時候纔去加載模塊文件,加載完再接着執行。
demo代碼詳見 https://github.com/BillyQin/jsModule/tree/master/commonJs
爲何瀏覽器中不支持 CommonJS 語法呢?
這是由於瀏覽器環境中並無 module、 exports、 require 等環境變量。
es6定義了新的模塊加載方案。
// 導出 const addr = 'China' const year = 2018 export { addr, year }
// 導入 import { addr, year } from './index.js'
和require.js(AMD)一致,將須要使用的模塊加載完再執行代碼。
CommonJS模塊輸出值的拷貝, ES6輸出值的引用。 CommonJS模塊輸出值的拷貝, 也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值。
CommonJS是運行時加載,ES6是編譯時輸出接口。 CommonJS加載的是一個對象,就是module.exports屬性。該對象只有在腳本運行完成後纔會生成。而es6模塊不是對象,對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。
在瀏覽器不支持es6的時候,若是要使用es6的語法,通常都會在項目里加入babel。
// es6 let firstName = 'Michael'; const lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year};
轉換後
Object.defineProperty(exports, "__esModule", { value: true }); var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; exports.firstName = firstName; exports.lastName = lastName; exports.year = year;
Babel 只是把 ES6 模塊語法轉爲 CommonJS 模塊語法,而瀏覽器不支持CommonJs。這時候webpack出動。
瀏覽器不支持CommonJs的本質是由於瀏覽器環境中並無 module、 exports、 require 等環境變量。 webpack 打包後的文件之因此在瀏覽器中能運行,就是靠模擬了這些變量的行爲。
// commonJs let multiply = require('./multiply') console.log('加載 square 模塊') let square = function (num) { return multiply.multiply(num, num) } module.exports = { square: square }
模擬後:
// 包裹一層,注入這些變量 function(module, exports, require) { console.log('加載了 square 模塊'); var multiply = require("./multiply"); module.exports = { square: function(num) { return multiply.multiply(num, num); } }; }
整個CommonJs項目改寫後
// 自執行函數 (function(modules){ // 存儲已加載的模塊 var installModules = {} // 關鍵的require方法 function require(moduleName) { if (installModules.moduleName) { return installModules.moduleName.exports } var module = installModules[moduleName] = { exports: {} } modules[moduleName](module, module.exports, require); return module.exports; } return require('main') })({ 'main': function(module, exports, require) { var addModule = require("./add"); console.log(addModule.add(1, 1)) var squareModule = require("./square"); console.log(squareModule.square(3)); }, './add': function(module, exports, require) { console.log('加載 add 模塊') var add = function (x, y) { return x + y } module.exports = { add: add } }, './multiply': function(module, exports, require) { console.log('加載 multiply 模塊') var multiply = function (x, y) { return x * y } module.exports = { multiply: multiply } }, './square': function(module, exports, require) { console.log('加載 square 模塊') var multiply = require('./multiply') var square = function (num) { return multiply.multiply(num, num) } module.exports = { square: square } } })
原文出處:https://www.cnblogs.com/BillyQin/p/10058454.html