本文将向你们分享一波搭建一个自动版本管理的Vue组件库的过程,偏基础向,若有不足之处恳请指出。javascript
为了让读者更清晰的了解每一步的步骤,有兴趣的盆友能够将demo克隆到本地(demo地址)使用git reset [commitId] --hard切换到每个commit查看细节。css
commitId给出以下:html
# | 描述 | commitId |
---|---|---|
1 | 搭建项目 | 02a4880146675adc902592b74248a0e3526df053 |
2 | 配置项目 | 598f4592c043eeb44aea840237c1a7726de3acfd |
3 | 编写组件 | ec9cc302317c1eded6eab9beda206c9ae51c88e5 |
4 | 打包组件 | 238a414231e926ec91feef5b9c501f339fedb0d6 |
5 | 发布npm包 | 1738eac3e0b8876bf6261ffd2255758100c6481b |
首先咱们基于@vue/cli建立一个vue项目,个人cli当前版本是4.1.2前端
npm i -g @vue/cli
vue create vue-component-lib-demo
复制代码
咱们的构建目标是个组件库,把Babel、TS、CSS预处理、Linter、单元测试勾上就成,安装依赖大概须要几分钟时间。 vue
项目建立好以后咱们须要进行一些配置:java
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>vue-component-lib-demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but vue-component-lib-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
复制代码
// main.ts
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
复制代码
// App.tsx
/** * 这里我使用了tsx来写vue组件 * 主要缘由是vue的tamplate对ts的支持不够 * 不习惯的同窗仍是能够用.vue文件,没有什么区别 */
import { Component, Vue } from 'vue-property-decorator';
@Component({
components: {
TestA
}
})
export default class App extends Vue {
protected render() {
return (
<div> hello world </div>
);
}
}
复制代码
"path": {
"@/*": [
"./*"
]
}
复制代码
// vue.config.js
const path = require('path')
module.exports = {
// sourceMap
productionSourceMap: false,
devServer: { // 本地服务配置
host: "localhost",
port: 3000,
hot: true,
compress: true,
hotOnly: true,
open: false,
https: false,
overlay: {
warning: false,
error: true
},
public: "0.0.0.0:3000"
},
// 指向example中的模版和入口文件
pages: {
index: {
entry: 'example/main.ts',
template: 'example/index.html',
filename: 'index.html'
}
},
css: {
extract: false // 将css内联,js和css但愿分开打包的同窗这里设置为true
},
configureWebpack: {
output: {
libraryExport: 'default'
},
},
// 插件选项
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
path.resolve(__dirname, './packages/common/style/common.less')
]
}
},
// webpack配置项
chainWebpack: config => {
config.externals({
'vue': 'Vue' // 咱们不但愿把vue的源码打包
})
}
}
复制代码
最终咱们的项目目录长这样: node
编写一个组件咱们须要建立:组件、组件的样式、组件的入口文件、组件的文档。 接下来以TestA为例咱们建立一个简单的组件,目录结构以下:webpack
css使用了css module:git
// TestA.tsx
import style from './TestA.module.less'
复制代码
直接在TestA.tsx中引入style会引发tslint报错找不到模块“./TestA.module.less”,这时候咱们须要在shims-vue.d.ts文件中对less文件添加一个描述:github
// shims-vue.d.ts
declare module "*.less" {
const less: any;
export default less;
}
复制代码
接下来咱们来编写TestA组件:
// TestA.tsx
import { Component, Vue } from 'vue-property-decorator';
import style from './TestA.module.less'
@Component({
name: 'TestA',
})
export default class TestA extends Vue {
protected render() {
return (
<span class={style.text}> TestA </span>
);
}
}
复制代码
TestA.module.less
.text{
color: purple;
}
复制代码
实现了TestA组件后咱们须要为他编写一个入口文件index.ts,用于按需加载:
// index.ts
import TestA from './TestA'
import { VueConstructor } from 'vue'
// 为TestA组件新增install方法,能够将TestA注册为全局组件
TestA['install'] = (Vue: VueConstructor): void => {
Vue.component(TestA.name, TestA)
}
export default TestA
复制代码
接下来咱们在/example/App.tsx里引入一下TestA组件看看效果:
import { Component, Vue } from 'vue-property-decorator';
import TestA from '../packages/components/TestA';
@Component({
components: {
TestA
}
})
export default class App extends Vue {
protected render() {
return (
<div> hello <TestA/> </div>
);
}
}
复制代码
看起来还8错:
按照编写组件的流程又新增了一个TestB组件,这时候咱们须要打包组件,须要提供一个总的入口文件,因而在/packages/下新增index.ts和config.ts,config.ts用于引入组件,可将组件重命名后导出到index.ts:
// packages/config.ts
import TestA from './components/TestA/TestA';
import TestB from './components/TestB/TestB';
export default {
TestA,
TestB
}
复制代码
// packages/index.ts
import config from './config'
import { VueConstructor } from 'vue'
interface compList {
[componentsName: string]: VueConstructor
}
const components: compList = config
const install = (Vue: VueConstructor): void => {
Object.keys(components).forEach((name) => Vue.component(name, components[name]))
}
export default {
install,
...components,
}
复制代码
index.ts文件导出一个install方法,将组件遍历注册到全局
接下来咱们在package.json中新增一条npm script:
"lib": "vue-cli-service build --target lib --name base-lib --dest lib packages/index.ts"
复制代码
这条命令的意思是vue-cli-service打包目标是组件库,入口文件是packages/index.ts,目标目录是lib,组件库的名字是base-lib,执行npm run lib后咱们获得了构建产物:
若是咱们每次组件库版本更新都须要手动更改package.json的version字段,很容易出错,并且人工维护版本也很是累,咱们可使用npm version命令来为咱们自动升级版本。
先安装一些相关依赖:
npm i -D cross-var shelljs inquirer
复制代码
接下来修改package.json:
"config": {
"target": "lib/$npm_package_version"
},
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint",
"lib": "cross-var vue-cli-service build --target lib --name base-lib --dest $npm_package_config_target packages/index.ts"
},
复制代码
新增了自定义变量config,其中target是咱们打包的目标目录,$npm_package_version是当前package.json的版本号,修改lib命令,将config.target指定为输出文件。
接下来咱们在根目录建立一个release.js,用于实现终端用户交互,询问用户此次发布要升级什么版本,npm version 遵循semver版本号,咱们可使用npm version方便的管理版本而不用手动管理
// release.js
const { exec } = require('shelljs')
const inquirer = require('inquirer')
inquirer.prompt([
{
type: 'list',
name: 'selected',
message: '请选择版本升级类型',
choices: [
'major',
{
name: '大版本更新',
disabled: '较大版本更新时选择此项'
},
'minor',
{
name: '小版本更新',
disabled: '较小版本更新时选择此项'
},
'patch',
{
name: '更新补丁',
disabled: '修复bug选择此项'
},
new inquirer.Separator(),
'cover',
{
name: '覆盖当前版本',
disabled: '危险操做!请勿覆盖线上运行版本!'
},
new inquirer.Separator(),
]
}
]).then(answer => {
if (answer.selected === 'cover') {
exec(`npm run lib`)
} else {
exec(`npm version ${answer.selected} && npm run lib`)
}
})
复制代码
而后新增一条npm script命令release:
"release": "node release.js"
复制代码
在咱们使用npm run release后咱们能够看到:
选择版本后会使用相应的npm version更新版本,打出来的包也在相应版本号文件夹里了:
修改package.json:
"private": false,
"main": "lib/baselib.umd.min.js",
"files": [
"packages",
"lib"
],
复制代码
将包改成非私有,指定入口文件和上传的文件。
接下来使用npm login登录帐号,使用npm publish便可发布到npm。
我是suhangdev,邮箱17816876697@163.com,欢迎与我交流前端相关话题,若是文章对你有帮助,请点赞支持噢👍~