在日常研发中,经常会遇到跨项目的通用样式组件,对于任何一家公司而言沉淀一套自己的UI库成本其实不高。这篇文章是关于如何最小成本利用vue-cli快速构建一套组件库的打包编译配置
我们需要打包输出什么
封装一个UI库同时支持按需引入,和全局引入,需要打包出以下文件
- 全局引入:一份CommonJS用于NPM
- 全局引入:一份UMD用于浏览器
- 全局引入:一份公用CSS
- 按需引入:按组件打包划分的CommonJS,CSS
如何使用cli打包
-
cli可以做到什么: 使用命令
vue-cli-service build --target lib --name myLib [entry]可以直接打包出CSS,UMD,CommonJS -
总思路:cli满足了我们所有所需的输出打包文件类型,那么只需要配置一份input-output的打包字典。依次循环vue-cli打包即可拿到我们所需的所有文件。
-
具体做法
- runjs循环执行cli打包命令
- node进行文件控制:移动,复制,文件遍历等(从dist中拿出所需的放入lib对应文件夹)
- chalk终端console样式控制
-
demo示例
// cli.build.js
const { run } = require('runjs')
const chalk = require('chalk')
const libList = require('../lib-list.js')
const config = require('./config.js')
const { move, fsExistsSync } = require('./file-handle')
const { chalkConsole } = require('./utils')
const fs = require('fs')
const files = []
const emptyCss = []
function build ({ input, output } = {}, index, arr) {
chalkConsole.building(index + 1, arr.length)
run(
`vue-cli-service build --target ${config.outputPath} --no-clean --name ${output} --dest dist ${input}`
)
files.push(output)
}
// 1打包
let pkg = []
Object.keys(libList).forEach((moduleName) => {
const { input, output } = libList[moduleName]
pkg.push({ input, output })
})
pkg.forEach(build)
// 2 移动CommonJS,css重命名文件
fsExistsSync(config.outputPath) || fs.mkdirSync(config.outputPath)
fs.mkdirSync(config.styleOutputPath)
files.forEach((file) => {
// 移动js
let path = `dist/${file}.common.js`
let target = `${config.outputPath}/${file}.js`
fsExistsSync(path) && move(path, target)
// 移动css
path = `dist/${file}.css`
target = file === 'eqx-ui.common' ? `${config.styleOutputPath}/index.css` : `${config.styleOutputPath}/${file}.css`
if (!fsExistsSync(path)) {
emptyCss.push(file)
}
fsExistsSync(path) && move(path, target)
})
// 3移动字体文件
fsExistsSync('dist/fonts') && move('dist/fonts', `${config.styleOutputPath}/fonts`)
// 用于给babel-plugin-component 按需加载
fsExistsSync('public/base.css') && fs.copyFile('public/base.css', `${config.styleOutputPath}/base.css`, function (_err) {})
chalkConsole.success()
console.warn(chalk.yellow(`没有css的模块:${emptyCss}`))
// lib-list.js input-output配置
const fs = require('fs')
function getComponents () {
let arr = fs.readdirSync('./components')
const ignore = ['scrollbar']
const rule = new RegExp(/^[\._]/)
arr = arr.filter(item => !ignore.includes(item) && !rule.test(item))
return arr
}
function getOpt () {
const components = getComponents()
let opt = {}
components.forEach(file => {
opt[file] = {
input: `components/${file}/index.js`,
output: file
}
})
return opt
}
module.exports = Object.assign({
index: {
input: 'index.js',
output: 'eqx-ui.common'
}
}, getOpt())