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