目前主流的前端框架vue和react都採用rollup來打包,爲了探索rollup的奧妙,接下來就讓咱們一步步來探索,並基於rollup搭建一個庫打包腳手架,來發布本身的庫和組件。javascript
寫rollup的文章是由於筆者最近要規範前端開發的業務流程和架構,並提供內部公有組件庫和工具庫供團隊使用。在查閱大量資料並對比了webpack和rollup的優缺點以後,最終選擇rollup來做爲打包工具,咱們最終要實現經過npm的方式安裝咱們的組件庫和工具庫:css
// 安裝
npm install @xuxi/tools
// 使用
import { sleep } from '@xuxi/tools'
複製代碼
下面咱們一步步來複盤rollup的配置過程和最佳實踐。前端
Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the new standardized format for code modules included in the ES6 revision of JavaScript, instead of previous idiosyncratic solutions such as CommonJS and AMD.vue
意思大體是說Rollup 是一個 JavaScript 模塊打包器,能夠將小塊代碼編譯成大塊複雜的代碼,例如 library 或應用程序。Rollup 對代碼模塊使用新的標準化格式,這些標準都包含在 JavaScript 的 ES6 版本中,而不是像CommonJS 和 AMD這種特殊解決方案。java
rollup最大的亮點就是Tree-shaking,便可以靜態分析代碼中的 import,並排除任何未使用的代碼。這容許咱們架構於現有工具和模塊之上,而不會增長額外的依賴或使項目的大小膨脹。若是用webpack作,雖然能夠實現tree-shaking,可是須要本身配置而且打包出來的代碼很是臃腫,因此對於庫文件和UI組件,rollup更加適合。node
首先咱們安裝一下rollup:react
npm i rollup -g
複製代碼
而後在本地建立一個項目:jquery
mkdir -p my-project
cd my-project
複製代碼
其次咱們建立一個入口並寫入以下代碼:webpack
// src/main.js
import say from './say.js';
export { say }
// src/say.js
export default function(name){
console.log(name)
};
複製代碼
基本代碼準備好了以後,咱們寫rollup的配置文件(rollup.config.js在根目錄下):ios
// rollup.config.js
export default {
input: 'src/main.js',
output: {
file: 'bundle.js',
format: 'cjs'
}
};
複製代碼
這樣,咱們在終端執行:
// --config 或 -c 來使用配置文件
rollup -c
複製代碼
這樣在更目錄下就生成了一個bundle.js,就是咱們想要的打包後的文件。咱們也能夠用package.json來設置打包配置信息,用npm run xxx來打包和測試代碼。
爲了更靈活的打包庫文件,咱們能夠配置rollup插件,比較實用的插件有:
打包一個庫用以上插件徹底夠用了,不過若是想實現對react等組件的代碼,能夠有更多的插件可使用,這裏就不一一介紹了。
咱們能夠這樣使用,相似於webpack的plugin配置:
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from "rollup-plugin-babel";
import { terser } from 'rollup-plugin-terser';
import { eslint } from 'rollup-plugin-eslint';
export default [
{
input: 'src/main.js',
output: {
name: 'timeout',
file: '/lib/tool.js',
format: 'umd'
},
plugins: [
resolve(), // 這樣 Rollup 能找到 `ms`
commonjs(), // 這樣 Rollup 能轉換 `ms` 爲一個ES模塊
eslint(),
babel(),
terser()
]
}
];
複製代碼
是否是很簡單呢?我的以爲比webpack的配置簡單不少。經過如上配置,雖然能實現基本的javascript文件打包,可是還不夠健壯,接下來咱們一步步來細化配置。
首先咱們先安裝babel相關模塊:
npm i core-js @babel/core @babel/preset-env @babel/plugin-transform-runtime
複製代碼
而後設置.babelrc文件
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"useBuiltIns": "usage",
"corejs": "2.6.10",
"targets": {
"ie": 10
}
}
]
],
"plugins": [
// 解決多個地方使用相同代碼致使打包重複的問題
["@babel/plugin-transform-runtime"]
],
"ignore": [
"node_modules/**"
]
}
複製代碼
@babel/preset-env能夠根據配置的目標瀏覽器或者運行環境來自動將ES2015+的代碼轉換爲es5。須要注意的是,咱們設置"modules": false,不然 Babel 會在 Rollup 有機會作處理以前,將咱們的模塊轉成 CommonJS,致使 Rollup 的一些處理失敗。
爲了解決多個地方使用相同代碼致使打包重複的問題,咱們須要在.babelrc的plugins裏配置@babel/plugin-transform-runtime,同時咱們須要修改rollup的配置文件:
babel({
exclude: 'node_modules/**', // 防止打包node_modules下的文件
runtimeHelpers: true, // 使plugin-transform-runtime生效
}),
複製代碼
若是你對babel不太熟,能夠看我以前webpack的文章或者去官網學習。
咱們能夠在package.json中配置不一樣的執行腳本和環境變量來對開發和生產作不一樣的配置:
// package.json
"scripts": {
"build": "NODE_ENV=production rollup -c",
"dev": "rollup -c -w",
"test": "node test/test.js"
},
複製代碼
咱們能夠手動導出NODE_ENV爲production和development來區分生產和開發環境,而後在代碼中經過process.env.NODE_ENV來獲取參數。這裏咱們主要用來設置在開發環境下不壓縮代碼:
const isDev = process.env.NODE_ENV !== 'production';
// ...
plugins: [
!isDev && terser()
]
複製代碼
咱們可使用上面的提到的rollup-plugin-eslint來配置:
eslint({
throwOnError: true,
throwOnWarning: true,
include: ['src/**'],
exclude: ['node_modules/**']
})
複製代碼
而後創建.eslintrc.js來根據本身風格配置具體檢測:
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"ENV": true
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
]
}
};
複製代碼
詳細的eslint配置能夠去官網學習。
使用rollup打包,咱們在本身的庫中須要使用第三方庫,例如lodash等,又不想在最終生成的打包文件中出現jquery。這個時候咱們就須要使用external屬性。好比咱們使用了lodash,
import _ from 'lodash'
// rollup.config.js
{
input: 'src/main.js',
external: ['lodash'],
globals: {
lodash: '_'
},
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' }
]
}
複製代碼
咱們能夠將本身的代碼導出成commonjs模塊,es模塊,以及瀏覽器能識別的模塊,經過以下方式設置:
{
input: 'src/main.js',
external: ['ms'],
output: [
{ file: pkg.main, format: 'cjs' },
{ file: pkg.module, format: 'es' },
{ file: pkg.module, format: 'umd' }
]
}
複製代碼
若是你是以前沒有註冊npm帳號,你能夠經過以下方式配置:
npm adduser
複製代碼
而後輸入用戶名,郵箱,密碼,最後使用npm publish發佈。這裏介紹包的配置文件,即package.json:
{
"name": "@alex_xu/time",
"version": "1.0.0",
"description": "common use js time lib",
"main": "dist/tool.cjs.js",
"module": "dist/time.esm.js",
"browser": "dist/time.umd.js",
"author": "alex_xu",
"homepage": "https://github.com/MrXujiang/timeout_rollup",
"keywords": [
"tools",
"javascript",
"library",
"time"
],
"dependencies": {
// ...
},
"devDependencies": {
// ...
},
"scripts": {
"build": "NODE_ENV=production rollup -c",
"dev": "rollup -c -w",
"test": "node test/test.js",
"pretest": "npm run build"
},
"files": [
"dist"
]
}
複製代碼
name是包的名字,能夠直接寫包名,好比loadash,或者添加域,相似於@koa/router這種,@後面是你npm註冊的用戶名。key爲包的關鍵字。
發佈後,咱們能夠用相似於下面這種方式安裝:
npm install @alex_xu/time
// 使用
import { sleep } from '@alex_xu/time'
// 或
const { sleep } = requrie('@alex_xu/time')
複製代碼
以下是安裝截圖:
在npm上也能夠搜索到本身的包: 是否是頗有成就感呢?快讓你們一塊兒使用你開發的包吧!完整配置文件我已經發布到github,地址: github.com/MrXujiang/t…
若是想了解更多webpack,gulp,css3,javascript,nodeJS,canvas等前端知識和實戰,歡迎在公衆號《趣談前端》加入咱們一塊兒學習討論,共同探索前端的邊界。