本文將向你們分享一波搭建一個自動版本管理的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,歡迎與我交流前端相關話題,若是文章對你有幫助,請點贊支持噢👍~