關於 rollupjs 的教程已經很是多了,但是較少看到比較完整的工程樣板,因此分享下我本身搭建的,已經在公司內部使用的樣板工程。javascript
如今的前端爲了打包一個插件,差很少下面的配置文件都是必須的;html
哪怕代碼僅僅一百多行,爲了保證質量,少了誰都不能少了下面的配置文件;前端
若是是 typescript 寫的,那就還要再加幾個,懷念幾年前 Happy Coding 的日子😀。java
Project/
├── README.md
├── package.json
├── rollup.config.js
├── babel.config.js
├── bundle-analyzer-report.html 構建分析報告
├── jsdoc.json 自動生成 api 文檔
├── .gitignore
├── .eslintrc.js 代碼檢查
├── .eslintignore
├── .editorconfig 統一編輯器風格用的配置文件
├── coverage/ 測試覆蓋率
├── dist/ 輸出目錄
├── dist-docs/ 文檔輸出目錄
├── .vscode/ vscode 編輯器配置目錄
├── src/
| ├── index.esm.js esm 輸出用
| └── index.js cjs 和 umd 輸出用
└── test/
├── fixtures/
├── unit/
└── .eslintrc.js
複製代碼
由於要支持 nodejs
與瀏覽器,因此須要輸出多種格式的文件,常見的輸出格式是 cjs
, esm
和 umd
三種格式,若是有必要也能夠在加上 iife
的格式。node
cjs
是 nodejs
風格的文件,主要是爲了給 node 端使用,屬於 commonjs 規範function foo () {}
exports.foo = foo
// or
module.exports = { foo }
複製代碼
esm
搭配 pkg.module
字段 主要是構建工具(webpack, rollupjs)在用,屬於 es module 規範export function foo () {}
// or
export { foo }
複製代碼
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'b'], function (exports, b) {
factory((root.commonJsStrictGlobal = exports), b);
});
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('b'));
} else {
// Browser globals
factory((root.commonJsStrictGlobal = {}), root.b);
}
}(typeof self !== 'undefined' ? self : this, function (exports, b) {
// Use b in some fashion.
// attach properties to the exports object to define
// the exported module properties.
exports.action = function () {};
}));
複製代碼
(function () {
// 代碼寫這裏
}())
複製代碼
推薦輸出:cjs, esm 和 umd 三種格式的文件webpack
推薦 babel 和 buble,具體選擇看我的選擇,這裏給出我選擇的理由git
babel 的使用場景es6
buble 的使用場景github
目前兩種都在用, babel 用於項目,buble 用於插件,由於插件能夠進行後編譯處理,免去代碼冗餘的問題web
推薦一:
斷言工具用 nodejs 自帶的 assert 或其餘的均可以
推薦二:
真心好用,惋惜尚未去深刻了解,正在入手中
沒有 e2e
的推薦,由於我也不熟
// 清理文件
import clear from 'rollup-plugin-clear'
// 執行進度(可選)
import progress from 'rollup-plugin-progress'
// 代碼檢查
import { eslint } from 'rollup-plugin-eslint'
// 去除不須要打包的外部依賴
import externals from 'rollup-plugin-node-externals'
// 字符串替換,相似 webpack 的 DefinePlugin
import replace from 'rollup-plugin-replace'
// 模塊引用
import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'
// json 文件處理(可選)
import json from 'rollup-plugin-json'
// 代碼壓縮
import { terser } from 'rollup-plugin-terser'
// 查看構建後的文件大小
import filesize from 'rollup-plugin-filesize'
// 用於分析構建後的代碼
import visualizer from 'rollup-plugin-visualizer'
複製代碼
{
// nodejs 入口
"main": "./dist/lib.commonjs.js",
// webpack,rollupjs 入口
"module": "./dist/lib.esm.js",
"scripts": {
// 用 cross-env 解決不一樣操做系統之間環境變量設置方式不一致的問題
"dev": "cross-env NODE_ENV=development rollup -cw rollup.config.js",
"build": "cross-env NODE_ENV=production rollup -c rollup.config.js"
}
}
複製代碼
rollupjs 支持輸出對象或數組形式的配置,因此不須要拆分紅多個配置文件.
const isProd = process.env.NODE_ENV === 'production'
// 配置輸出格式
export default mergeConfig(baseConfig, [
{
input: 'src/index.esm.js',
output: {
banner,
file: 'dist/lib.esm.js',
format: 'es'
}
},
{
input: 'src/index.js',
output: {
file: 'dist/lib.commonjs.js',
format: 'cjs'
}
},
{
input: './src/index.js',
output: {
file: `./dist/lib${isProd ? '.min' : ''}.js`,
format: 'umd'
},
plugins: [
isProd && terser(),
process.env.npm_config_report && visualizer({
title: `${pkg.name} - ${pkg.author.name}`,
filename: 'bundle-analyzer-report.html'
})
]
}
])
複製代碼
module.exports = {
presets: [
['@babel/preset-env',{
// rollupjs 會處理模塊,因此設置成 false
modules: false
}]
],
plugins: [
// 避免 babel 將 async/await 轉成 Generator
// 這樣兼容性更好
'transform-async-to-promises'
]
}
複製代碼
module.exports = {
root: true,
env: {
// 用於跳過各自環境的全局變量,也能夠分開使用 node 和 browser 屬性
'shared-node-browser': true,
es6: true
},
rules: {
// 構建時避免 console 和 debugger 被一塊兒構建上去
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
// 爲了語法解析
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
}
}
複製代碼
# 執行構建命令
$ npm run build --report
複製代碼
# 執行構建命令而且生成 html 報告
$ npm run build --report
複製代碼
{
"scripts": {
// test 還可能包含測試數據文件,因此不能直接使用通配符
"test": "cross-env NODE_ENV=test nyc mocha \"test/{**/*,*}.test.js\"",
"report": "nyc report --reporter=html"
},
// 配置 nyc 插件
"nyc": {
"require": [
// 爲了能跑 es6 的代碼
"@babel/register"
],
"reporter": [
"text-summary"
]
}
}
複製代碼
{
"env": {
// eslint 預設了 mocha 的全局變量,因此設置爲 true 就能夠了
"mocha": true
}
}
複製代碼
注意 eslint 的配置會繼承項目根目錄的 eslint 的配置信息
const pkg = require('./package.json')
module.exports = {
presets: [
['@babel/preset-env', {
// 測試時模塊須要轉換
modules: process.env.NODE_ENV === 'test' ? 'commonjs' : false
}]
],
// 配置測試時用到的插件
env: {
test: {
plugins: [
'istanbul',
'inline-json-import',
// 路徑別名,否則就只能用長長的路徑進行模塊引用了
['module-resolver',
{
root: ['./src/'],
alias: {
[pkg.name]: './src/index.esm.js'
}
}
]
]
}
}
}
複製代碼
# 運行測試命令
$ npm test
複製代碼
# 查看測試報告
$ npm run report
複製代碼
這裏使用的是 jsdoc 工具
{
"scripts": {
"build:docs": "jsdoc -c jsdoc.json"
}
}
複製代碼
{
"source": {
"include": ["src"]
},
"templates": {
"cleverLinks": false,
"monospaceLinks": false
},
"tags": {
"allowUnknownTags": false
},
"opts": {
"verbose": true,
"recurse": true,
"encoding": "utf8",
"readme": "README.md",
"destination": "dist-docs",
// 建議添加,由於這樣能夠一個版本一個文檔
"package": "package.json"
}
}
複製代碼
還能夠作的事情有:
這些都是須要人工去配置的,當所有配置完畢後,一個擁有完善功能的項目也就配置完畢,這樣的項目才能夠被認爲是一個工程了吧。
最後獻上個人 github 地址,歡迎 fork