有同學(xué)開(kāi)發(fā)了一個(gè)組件庫(kù),可被模塊化給坑死了......
Hello,大家好,我是 Sunday。
最近有同學(xué)開(kāi)發(fā)了一套自己的組件庫(kù),目前組件已經(jīng)儲(chǔ)備了 30 多個(gè)。但是,在 打包的時(shí)候 可遇到了不少的坑。
我們知道,庫(kù)的打包一般推薦使用 rollup。不過(guò) rollup 使用起來(lái)可并不簡(jiǎn)單,特別是 打包格式的問(wèn)題!。庫(kù)的打包格式劃分要比項(xiàng)目復(fù)雜的多,涉及到 IIFE、UMD、ESM、CJS 等多種格式方案。
那么這些打包格式到底要怎么使用?每一個(gè)又代表的是什么意思呢?
今天咱們就針對(duì)這個(gè)問(wèn)題,來(lái)統(tǒng)一為大家解釋一下!
為什么要關(guān)注打包格式?
打包格式本質(zhì)上決定了我們打包后的代碼該如何在不同的環(huán)境下運(yùn)行。
比如,你可能會(huì)打包一個(gè)工具庫(kù),希望它既能在瀏覽器環(huán)境下以 <script> 引入,也能在 Node.js 中通過(guò) require 引入,還能通過(guò) import 在現(xiàn)代的模塊化項(xiàng)目中使用。不同的場(chǎng)景需要不同的打包格式支持,那么想要達(dá)成這樣的目的,我們就必須要了解打包格式!
目前常見(jiàn)的打包格式主要有 4 種,分別為:IIFE、UMD、ESM、CJS。
1. IIFE (Immediately Invoked Function Expression)
IIFE(立即執(zhí)行函數(shù)表達(dá)式)是一種將代碼包裹在立即執(zhí)行的函數(shù)中的打包格式。這種格式可以直接在瀏覽器中運(yùn)行,因?yàn)樗写a都被封裝在一個(gè)函數(shù)里,所以不會(huì)污染全局作用域。
使用場(chǎng)景
適合直接用 <script> 標(biāo)簽引入的場(chǎng)景,在這種情況下,你只需要加載文件,就可以立即運(yùn)行。
代碼示例
// Rollup 配置
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.iife.js',
format: 'iife', // IIFE 格式
name: 'MyLibrary', // 全局變量名
}
};
上面的配置會(huì)生成一個(gè) IIFE 格式的文件。假設(shè)你的庫(kù)名為 MyLibrary,在瀏覽器中引入這個(gè)打包文件后,就可以通過(guò) window.MyLibrary 訪問(wèn)你的庫(kù)。
打包結(jié)果示例
(function () {
'use strict';
function sayHello() {
console.log('Hello, World!');
}
window.MyLibrary = { sayHello };
})();
這里可以看到所有代碼被包裹在一個(gè)立即執(zhí)行函數(shù)中。因?yàn)槲覀冎付?nbsp;name: 'MyLibrary',最終結(jié)果會(huì)掛載到 window.MyLibrary 下。
2. UMD (Universal Module Definition)
UMD(通用模塊定義)是一個(gè)兼容性極強(qiáng)的格式,它同時(shí)支持 AMD(異步模塊定義)和 CommonJS 模塊規(guī)范。也就是說(shuō),不管你是在瀏覽器、Node.js,還是其他模塊加載器環(huán)境中,UMD 格式都能適用。
使用場(chǎng)景
適合需要兼容性強(qiáng)的庫(kù),既希望支持 require 引入,也希望能在瀏覽器中通過(guò) <script> 引入的場(chǎng)景。
代碼示例
// Rollup 配置
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.umd.js',
format: 'umd', // UMD 格式
name: 'MyLibrary'
}
};
打包結(jié)果示例
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.MyLibrary = factory());
}(this, (function () {
'use strict';
function sayHello() {
console.log('Hello, World!');
}
return { sayHello };
})));
UMD 格式的代碼根據(jù)不同的環(huán)境,選擇不同的導(dǎo)出方式:
- 如果檢測(cè)到 module.exports 存在,則導(dǎo)出為 CommonJS;
- 如果 define.amd 存在,則支持 AMD。
- 否則,將庫(kù)掛載到全局對(duì)象(在瀏覽器環(huán)境中通常是 window)。
3. ESM (ES Module)
ESM(ES 模塊)是 ES6 規(guī)范下的模塊化格式。
ESM 格式支持 import 和 export,在現(xiàn)代瀏覽器以及支持模塊化的環(huán)境(比如 Node.js >=12)中,ESM 是首選格式,因?yàn)樗诩虞d效率、按需加載方面都有天然優(yōu)勢(shì)。
使用場(chǎng)景
適合現(xiàn)代的模塊化項(xiàng)目,通過(guò) import 和 export 語(yǔ)法進(jìn)行模塊導(dǎo)入導(dǎo)出。
代碼示例
// Rollup 配置
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.esm.js',
format: 'es' // ESM 格式
}
};
打包結(jié)果示例
// bundle.esm.js
function sayHello() {
console.log('Hello, World!');
}
export { sayHello };
這里我們直接使用了 export,ESM 格式生成的代碼可以直接被其他模塊通過(guò) import 引入,而不需要任何額外的包裝。
4. CJS (CommonJS)
CJS(CommonJS)是 Node.js 的模塊規(guī)范。
在 CommonJS 中,使用 module.exports 和 require 來(lái)導(dǎo)出和導(dǎo)入模塊。CJS 格式在 Node.js 環(huán)境中非常常見(jiàn)。
使用場(chǎng)景
適合在 Node.js 環(huán)境中使用的庫(kù),適合需要使用 require 的場(chǎng)景。
代碼示例
// Rollup 配置
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.cjs.js',
format: 'cjs' // CJS 格式
}
};
打包結(jié)果示例
'use strict';
function sayHello() {
console.log('Hello, World!');
}
module.exports = { sayHello };
在 CJS 格式下,我們通過(guò) module.exports 導(dǎo)出函數(shù)或?qū)ο?,這樣其他文件就可以使用 require 導(dǎo)入該模塊。
如何選擇正確的格式
在使用 Rollup 打包時(shí),我們應(yīng)該根據(jù)使用場(chǎng)景選擇合適的格式:
- IIFE:適合直接在瀏覽器中以 <script> 方式引入,不需要模塊化的支持。
- UMD:適合需要支持多種加載方式的庫(kù),兼容性最好。
- ESM:首選的現(xiàn)代模塊格式,適合現(xiàn)代模塊化項(xiàng)目。
- CJS:適合在 Node.js 環(huán)境中使用的模塊。
多格式輸出的組合
為了兼容不同的使用場(chǎng)景,很多庫(kù)會(huì)選擇同時(shí)輸出多種格式。即:我們可以通過(guò)一種統(tǒng)一的配置,一次性完成多種格式的輸出:
// Rollup 配置
export default {
input: 'src/index.js',
output: [
{ file: 'dist/bundle.iife.js', format: 'iife', name: 'MyLibrary' },
{ file: 'dist/bundle.umd.js', format: 'umd', name: 'MyLibrary' },
{ file: 'dist/bundle.esm.js', format: 'es' },
{ file: 'dist/bundle.cjs.js', format: 'cjs' }
]
};
這樣配置后,Rollup 會(huì)生成四種不同格式的文件,我們可以根據(jù)需要,選擇合適的文件進(jìn)行引入。