rollup打包js的注意點-haorooms部落格分享
前言
rollup比較適合打包js的sdk或者封裝的框架等,例如,vue原始碼就是rollup打包的。webpack比較適合打包一些應用,例如SPA或者同構專案等等。最近我們對rollup小試牛刀了一下。簡單分享一些注意事項吧。
rollup基礎
rollup基礎知識及外掛的一些使用,網上有不少資料,可以去查閱。
rollup中文網:www.rollupjs.com/guide/zh#-d…
問題記錄吧
下面主要記錄一下rollup使用過程中的一些報錯及解決方案吧。
錯誤一:
You must supply options.name for IIFE bundles
出現這個報錯,是要在options中指定name,例如如下:
output: {
file: resolve(`js/haorooms.${type}.js`),
format: type,
name: 'haorooms',
banner
},
複製程式碼
錯誤二
[!] (commonjs plugin) SyntaxError: Unexpected token
出現這個問題,可能有幾個原因
1、rollup-plugin-commonjs未引入,或者載入循序不對
我們知道,webpack loader是有載入循序的(從右到左,從下到上),rollup雖然沒有嚴格的載入循序,但是我通常是將commonjs放到babel編譯之後。如下:
babel({
exclude: 'node_modules/**', // 排除node_modules 下的檔案
runtimeHelpers: true
}),
commonjs(),
複製程式碼
2、缺少babel類 我按照babel類熟悉編譯外掛作為這個專案的依賴。
npm install --save-dev babel-plugin-transform-class-properties
複製程式碼
.babelrc配置如下:
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-runtime", "external-helpers","transform-class-properties"]
}
複製程式碼
注:上面的配置是babel 7.0以下的方式,假如babel7.0以上,用另外的方式配置,參見:babeljs.io/docs/en/v7-…
錯誤三
code: 'BAD_BUNDLE_TRANSFORMER', plugin: 'uglify'
這個問題比較坑爹,其實我用rollup打包demo程式碼是沒有問題的,但是打包我的js就有問題了,好奇怪,後來我發現是swiper的問題,因為我依賴了swiper。關於swiper打包,在webpack中也有問題,通常babel打包之後,並不會把swiper的es6語法轉換。有時候webapck也會報錯,大致是
dom7 undefined ..
複製程式碼
webpack解決方案如下:
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'swiper': 'swiper/dist/js/swiper.js',
'@': resolve('src')
}
},
複製程式碼
指定一個別名
但是發現rollup中好像沒有這個方式,無奈,我在引入swiper的時候如下處理
import Swiper from 'swiper/dist/js/swiper.js'
複製程式碼
這樣打包的時候就不會有問題了。
錯誤四
process not defined
複製程式碼
這個錯誤是在打包成功之後,瀏覽器執行發現的,發現打包之後的程式碼中有process.env.NODE_ENV
解決方案:
import replace from 'rollup-plugin-replace'
const env = process.env.NODE_ENV
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify(env)
}),
]
複製程式碼
把 process.env.NODE_ENV這個替換掉
rollup 批量打包的方式
我們用rollup打包,一般都會打如下方式
amd – 非同步模組定義,用於像RequireJS這樣的模組載入器
cjs – CommonJS,適用於 Node 和 Browserify/Webpack
es – 將軟體包儲存為ES模組檔案
iife – 一個自動執行的功能,適合作為<script>標籤。(如果要為應用程式建立一個捆綁包,您可能想要使用它,因為它會使檔案大小變小。)
umd – 通用模組定義,以amd,cjs 和 iife 為一體
複製程式碼
我是用node,迴圈讀取的方式,配置如下:
const babel = require('rollup-plugin-babel')
const node = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const json = require('rollup-plugin-json')
const replace = require('rollup-plugin-replace')
const uglify = require('rollup-plugin-uglify')
// 新增 rollup-plugin-postcss 外掛
const postcss = require('rollup-plugin-postcss')
// 新增 postcss plugins
const simplevars = require('postcss-simple-vars')
const nested = require('postcss-nested')
const cssnext = require('postcss-cssnext')
const cssnano = require('cssnano')
const version = process.env.VERSION || require('../package.json').version
const path = require('path')
const fs = require('fs')
const ora = require('ora')
const terser = require('terser')
const zlib = require('zlib')
const spinner = ora('building for production...')
spinner.start()
const rollup = require('rollup')
if (!fs.existsSync('dist')) {
fs.mkdirSync('dist')
}
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
const banner =
'/*!\n' +
` * haoroomsjssdk v${version}\n` +
` * (c) 2017-${new Date().getFullYear()}\n` +
' * Released under the MIT License.\n' +
' */'
// amd – 非同步模組定義,用於像RequireJS這樣的模組載入器
// cjs – CommonJS,適用於 Node 和 Browserify/Webpack
// es – 將軟體包儲存為ES模組檔案
// iife – 一個自動執行的功能,適合作為<script>標籤。(如果要為應用程式建立一個捆綁包,您可能想要使用它,因為它會使檔案大小變小。)
// umd – 通用模組定義,以amd,cjs 和 iife 為一體
const buildArray = ['amd', 'cjs', 'iife', 'umd']
let allConfig = []
const env = process.env.NODE_ENV
let baseConfig = {
plugins: [
postcss({
extensions: ['.css'],
plugins: [
simplevars(),
nested(),
cssnext({ warnForDuplicates: false }),
cssnano()
]
}),
node({
jsnext: true, // 該屬性是指定將Node包轉換為ES2015模組
// main 和 browser 屬性將使外掛決定將那些檔案應用到bundle中
main: true, // Default: true
browser: true // Default: false
}),
json(),
babel({
exclude: 'node_modules/**', // 排除node_modules 下的檔案
runtimeHelpers: true
}),
commonjs(),
replace({
'process.env.NODE_ENV': JSON.stringify(env)
}),
(env === 'production' && uglify())
]
}
buildArray.forEach(item => {
let outputs = {
input: resolve('src/haorooms.js'),
output: {
file: resolve(`js/haorooms.${item}.min.js`),
format: item,
name: 'haorooms',
banner
}
}
allConfig.push(Object.assign({}, baseConfig, outputs))
})
function build (builds) {
let built = 0
const total = builds.length
const next = () => {
buildEntry(builds[built]).then(() => {
built++
if (built < total) {
next()
} else {
spinner.stop()
}
}).catch(logError)
}
next()
}
function buildEntry (config) {
const output = config.output
const { file, banner } = output
const isProd = /min\.js$/.test(file)
return rollup.rollup(config)
.then(bundle => bundle.generate(output))
.then(({ code }) => {
if (isProd) {
const minified = (banner ? banner + '\n' : '') + terser.minify(code, {
output: {
ascii_only: true
},
compress: {
pure_funcs: ['makeMap']
}
}).code
return write(file, minified, true)
} else {
return write(file, code)
}
})
}
function write (dest, code, zip) {
return new Promise((resolve, reject) => {
function report (extra) {
console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ''))
resolve()
}
fs.writeFile(dest, code, err => {
if (err) return reject(err)
if (zip) {
zlib.gzip(code, (err, zipped) => {
if (err) return reject(err)
report(' (gzipped: ' + getSize(zipped) + ')')
})
} else {
report()
}
})
})
}
function getSize (code) {
return (code.length / 1024).toFixed(2) + 'kb'
}
function logError (e) {
console.log(e)
}
function blue (str) {
return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}
build(allConfig)
複製程式碼
執行的時候直接如下:
cross-env NODE_ENV=production node 上面的檔名
複製程式碼
備註:cross-env 可以指定環境變數等
另外一種方式是用npm run all
參見地址:www.npmjs.com/package/npm…
可以用這個來執行多個npm 命令,來達到執行一次,打包所有的功能!
文章出處:
本文來源haorooms部落格:www.haorooms.com/post/rollup…