注意:cjs、amd、cmd、 ES Modules 都是隻規範,因此可能對應有多種實現css
下面就對各個模塊化方案作簡單說明html
<script src="jquery.js"></script>
<script src="jquery_scroller.js"></script>
<script src="main.js"></script>
<script src="other1.js"></script>
<script src="other2.js"></script>
<script src="other3.js"></script>
複製代碼
無模塊化時代的問題node
function compiledWrapper(exports, require, module, __filename, __dirname) {
// 插入文件中的代碼
// 返回導出對象
return module.exports
}
compiledWrapper.call(exports, exports, require, module, filename, dirname)
複製代碼
node index.js
,會有什麼結果?lib.jsjquery
// lib.js
let counter = 3
function incCounter() {
counter++
}
module.exports = {
counter,
incCounter
}
複製代碼
index.jswebpack
// index.js
const mod = require('./lib') // 此處輸出值?
console.log(mod.counter)
mod.incCounter() // 此處輸出值?
console.log(mod.counter)
複製代碼
a.jsgit
// a.js
console.log('a starting')
exports.done = false
const b = require('./b.js')
console.log('in a, b.done = %j', b.done)
exports.done = true
console.log('a done')
複製代碼
b.jsgithub
// b.js
console.log('b starting')
exports.done = false
const a = require('./a.js')
console.log('in b, a.done = %j', a.done)
exports.done = true
console.log('b done')
複製代碼
main.jsweb
// main.js
console.log('main starting')
const a = require('./a.js')
const b = require('./b.js')
console.log('in main, a.done = %j, b.done = %j', a.done, b.done)
複製代碼
require.config({
paths: {
// 若是第一個加載失敗就會加載第二個
jquery: ['lib/jquery.min', 'lib/jquery'],
lodash: 'lib/lodash.min',
main: './mian' // 入口文件
}
})
複製代碼
/** * 定義模塊,當依賴加載完成後執行回調 * 回調可返回值,返回值會被導出到外部使用 * @param {String} id 模塊名稱,可省略 * @param {Array} dependencies 依賴的模塊 * @param {Function} factory 回調函數 */
define(id?, dependencies?, factory);
複製代碼
define(['jquery'], function($) {
$('body').css({ background: 'red' })
// 導出log函數
return (...args) => console.log('自定義log', ...args)
})
複製代碼
/** * 加載模塊 * @param {Array} deps 要加載的模塊 * @param {Function} callback 加載成功回調,回調參數爲加載模塊導出對象 * @param {Function} errback 加載失敗回調 */
requirejs(deps, callback, errback)
複製代碼
require(['main'], log => {
log('我成功加載了‘)
// do something...,也能夠在這裏繼續require其餘js文件
})
複製代碼
.
├── index.html
└── js
├── lib
│ ├── jquery.js
│ ├── lodash.js
│ └── require.js
├── main.js
└── time.js
複製代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>requirejs-demo</title>
</head>
<body>
<h1 id="time"></h1>
<script src="./js/lib/require.js" data-main="./js/main.js"></script>
</body>
</html>
複製代碼
requirejs.config({
baseUrl: '/js/‘,
paths: {
jquery: './lib/jquery‘,
lodash: './lib/lodash‘
}
})require(['jquery', './js/time.js'], ($, time) => {
$('#time').text('TIME: ' + time.getTime())
setInterval(() => {
$('#time').text('TIME: ' + time.getTime())
}, 1000)
})
複製代碼
define(['jquery', 'lodash'], ($, _) => ({
getTime() {
const time = new Date()
const year = time.getFullYear()
const month = _.padStart(time.getMonth() + 1, 2, '0‘)
const date = _.padStart(time.getDate(), 2, '0‘)
const hour = _.padStart(time.getHours(), 2, '0‘)
const minute = _.padStart(time.getMinutes(), 2, '0‘)
const second = _.padStart(time.getSeconds(), 2, '0‘)
return `${year}/${month}/${date} ${hour}:${minute}:${second}`
}
}))
複製代碼
// CMD
// 代碼寫起來有同步require的感受
define((require, exports, module) => {
const $ = require('jquery‘)
$('title').text('hello')
})
複製代碼
// AMD
// 明顯的異步風格
define(['jquery'], $ => {
$('title').text('hello')
})
複製代碼
// 錯誤!
define(function(req) {
// ...
}) // 正確!
define(function(require) {
// ...
})
複製代碼
// 錯誤!
require(myModule) // 錯誤!
require('my-' + 'module') // 錯誤!
require('MY-MODULE'.toLowerCase()) // 正確!
require('my-module')
複製代碼
// 錯誤 - 重命名 "require"!
var req = require,
mod = req('./mod') // 錯誤 - 重定義 "require"!
require = function() {} // 錯誤 - 重定義 "require" 爲函數參數!
function F(require) {} // 錯誤 - 在內嵌做用域內重定義了 "require"!
function F() {
var require = function() {}
}
複製代碼
$
爲 nullfunction func(require, exports, module) {
const $ = require('jquery‘)
console.log($)
}
func.toString = () => '() => {}'
define(func)
複製代碼
seajs 對於 require 和 define 函數的特殊要求是因爲,seajs 原理致使的,seajs 的執行流程大體以下 api
.
├── index.html
└── js
├── lib
│ ├── jquery.js
│ ├── lodash.js
│ └── sea.js
├── main.js
└── time.js
複製代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="「UTF-8」" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>seajs-demo</title>
</head>
<body>
<h1 id="time"></h1>
<script src="./js/lib/sea.js" data-main="./js/main.js"></script>
<script> seajs.config({ base: '/js/‘, alias: { jquery: './lib/jquery‘, lodash: './lib/lodash‘ } }) // 加載入口模塊 seajs.use('./js/main.js') </script>
</body>
</html>
複製代碼
define((require, exports, module) => {
const $ = require('jquery‘)
const time = require('./time.js‘)
$('#time').text('TIME: ' + time.getTime())
setInterval(() => {
$('#time').text('TIME: ' + time.getTime())
}, 1000)
})
複製代碼
define((require, exports, module) => {
module.exports = {
getTime() {
const $ = require('jquery‘)
const _ = require('lodash‘)
const time = new Date()
const year = time.getFullYear()
const month = _.padStart(time.getMonth() + 1, 2, '0‘)
const date = _.padStart(time.getDate(), 2, '0‘)
const hour = _.padStart(time.getHours(), 2, '0‘)
const minute = _.padStart(time.getMinutes(), 2, '0‘)
const second = _.padStart(time.getSeconds(), 2, '0‘)
return `${year}/${month}/${date} ${hour}:${minute}:${second}`
}
}
})
複製代碼
node --experimental-modules index.mjs
,會有什麼結果?lib.mjs瀏覽器
// lib.mjs
export let counter = 3
export function incCounter() {
counter++
}
複製代碼
index.mjs
// index.mjs
import * as mod from './lib’
// 此處輸出值?console.log(mod.counter)
mod.incCounter()
// 此處輸出值?
console.log(mod.counter)
複製代碼
請問執行node --experimental-modules main.mjs
後會輸出什麼內容 a.mjs
// a.mjs
import { bar } from './b.mjs'
console.log('a.mjs')
console.log(bar)
export let foo = 'foo'
複製代碼
b.mjs
// b.mjs
import { foo } from './a.mjs'
console.log('b.mjs')
console.log(foo)
export let bar = 'bar'
複製代碼
main.mjs
// main.mjs
import './a.mjs'
複製代碼
歡迎關注 nashaofu