在实际开发中,我们除了常用的几种ui组件库外,可能还会有涉及到的公司定制化业务,需要我们自定义自己的组件库,并打包发布到私服npm上,以下为步骤:
- 创建项目开发并业务组件;
- 打包组件;
- 搭建私服npm;
- 发布组件到私服npm;
- 可能需要国际化(按需);
- 搭建组件库文档。
注意:因为涉及到部分版本信息,所以这里用到的npm版本7.24.0,node版本16.17.0
一、 创建项目
- 创建vue2项目。
vue create demo-ui
- 项目结构
在项目的根目录下创建conponents文件夹,如上图。
- 修改vue.config.js 新增pages属性,修改入口的配置,如下所示:
//vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
pages:{
index:{
entry:'src/main.ts',
template:'public/index.html',
filename:'index.html'
}
},
})
- components文件夹如下:
- 建立css文件夹和lib文件夹
- css文件夹用于存放样式文件
这里用到了sass,所以我们需要安装sass,版本如下:
"node-sass": "4.14.1",
"sass": "1.26.2",
"sass-loader": "^13.2.0",
我是用yarn安装的,命令如下:
yarn add sass node-sass@4.14.1 sass-loader@13.2.0
同时新建css文件,文件结构还是如上图。
index.scss:
@import "./card.scss";
card.scss:
// card的相关css配置;
- lib文件夹用于存放各个组件,并建立主index.js导出全部组件
// lib/index.js
import Card from './card';
const components = {
Card
}
const install = function(Vue){
if(install.installed) return;
Object.keys(components).forEach(key =>{
Vue.component(components[key].name,components[key])
})
}
const API = {
install
}
export default API;
export {
Card
}
- 组件开发。
一个组件是一个单独的文件夹,在components/lib文件下建立对应的文件夹,比如card:
建立card/src/main.vue和card/index.js两个文件,
card目录如下:
/components/lib/card/main.vue内容如下:
<template>
<div class="demo" :style="width ? {width: width + 'px'} : {}">
<div class="demo-card-img" :style="imgHeight? {height:imgHeight+'px'}:{}">
<img :src="imgSrc" alt="img" />
</div>
<div class="demo-card-summary" v-if="summary">
{{summary}}
</div>
<div v-else class="demo-card-summary">
<slot></slot>
</div>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name:'demo-card',
props: {
width: { //卡片宽度
type:Number,
default:0
},
imgSrc: { //卡片图片资源
type:String,
default:''
},
imgHeight: { //图片高度
type:Number,
default:0
},
summary: { //卡片概要
type:String,
default:''
},
}
}
</script>
<style>
</style>
components/lib/card/index.js内容如下:
import Card from './src/main.vue'
Card.install = function(Vue) {
Vue.component(Card.name,Card)
}
export default Card
main.ts中引入(这里我用到的语法是ts)
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import '../components/css/card.scss'
import Card from '../components/lib/card/index'
Vue.use(Card)
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
- App.vue中使用卡片组件
<template>
<div id="app">
<m-card
imgSrc="logo.png"
summary="这是一个自定义的demo组件"
>
<template v-slot:footer>
<div class="footer">
<div class="left">这是第一行</div>
<div class="right">这是第二行</div>
</div>
</template>
</m-card>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
执行yarn serve启动vue项目,查看组件效果,卡片显示如下:
二、组件库打包 这里用到的是webpack和gulp打包。
- 根目录下创建文件webpack.components.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const glob = require('glob')
const list = {}
async function makeList(dirPath,list){
const files = glob.sync(`${dirPath}/**/index.js`)
for(let file of files) {
const component = file.split(/[/.]/)[2]
list[component] = `./${file}`
}
}
makeList('components/lib',list)
module.exports = {
entry:list,
mode:'development',
output: {
filename:'[name].umd.js',
path:path.resolve(__dirname,'dist'),
library:'rui',
libraryTarget:'umd'
},
plugins: [
new VueLoaderPlugin()
],
module:{
rules: [
{
test:/\.vue$/,
use: [
{
loader: 'vue-loader'
}
]
},
{test:/\.css$/, use: ['css-loader']},
{test:/\.scss$/, use: ['css-loader','sass-loader',]},
{test:/\.(jpg|png|gif|bmp|jpeg)$/, loader: 'url-loader'},
{test:/\.(ttf|eot|svg|woff|woff2)$/,use: 'url-loader'}
]
}
}
- package.json中添加打包命令
"build:js": "webpack --config ./webpack.components.js"
4. 执行打包命令,将js打包为umd模块
yarn build:js
效果如下图:
执行后如果提示需要安装webpack-cli,输入yes安装即可。
index.umd.js提供整个组件库的引入使用;
card.umd.js可提供组件库的按需引入。
如果webpack打包js报错vue-loader.....,则安装对应的依赖:
yarn add vue-loader@15.9.8
yarn add vue-template-compiler@2.7.14
注意 vue-template-compiler@2.7.14 这儿的版本需要和vue的版本一致,可通过vue -v来获取当前版本,若安装的不一致,也会报错提示你的版本应该是多少。
- 使用gulp打包css文件。
- 根目录新建gulpfile.js
安装gulp相关的依赖,
yarn add gulp gulp-sass gulp-minify-css
//gulpfile.js
const gulp = require('gulp');
const sass = require('gulp-sass')( require ( 'sass' ) ) //sass转成css
const minifyCSS = require('gulp-minify-css') //压缩
gulp.task('sass',async function(){
return gulp.src('components/css/**/*.scss')
.pipe(sass())
.pipe(minifyCSS())
.pipe(gulp.dest('dist/css'))
})
- package.json添加打包命令
"build:css": "npx gulp sass",
- 执行打包命令,将css打包
yarn build:css
若打包时sass报错,则删掉重新安装sass。
正确时输入如下:
也可整合js和css打包命令
"build:lib": "npm run build:js && npm run build:css"
执行yarn build:lib,一键打包js和css文件,
控制台输出如下:
三、搭建自己的私服npm
使用verdaccio搭建npm私服,发布组件库。verdaccio官方文档
1、安装和配置
yarn global add verdaccio
成功后启动:
verdaccio
这里要注意第一行打印的信息,这个yaml文件就是verdaccio的配置文件,后面我们需要修改该文件进行相关配置。
2、启动成功后,直接在浏览器输入服务器的ip地址 + 最后一行打印出的端口号,看到这样的页面就说明安装成功了。如果访问不了可能是因为服务器防火墙没关,可以检查下防火墙。
3、修改配置文件 config.yaml
用记事本打开config.yaml,修改两个位置:
- 把listen改成自己的域名地址;
ax_users设为 -1,禁止注册用户,一般情况下都应该由管理员派发账号,禁用后再添加用户会直接报错
如下图:
注意 listen不要换行,不然会失败。
禁用后我们可以通过这个网站 添加账号密码,然后分发给对应的人
复制红框内生成的密码,创建htpasswd文件并将密码copy进去。
四、发布到私服npm。
1、package.json文件修改
"private": false,//这里要设置成false
"description": "自定义组件demo",
"main": "./dist/index.umd.js",//指定入口文件
"keywords": [ // 关键字,方便搜索
"vue",
"typescript",
"demo-ui",
"demoui",
"element-ui"
],
"author": "admin", //作者
"files": [ //指定发布的文件目录
"dist",
"components"
],
2、安装nrm并切换npm源到我们私有的仓库地址
这里使用到了nrm来管理npm registry
yarn add global nrm
// 添加自定义的源 源就是启动verdaccio时打印出来的地址
nrm add demo-ui http://1xx.xx.xx:xxxx/
// 查看所有可用的源
nrm ls
// 切换源到我们的私有仓库
nrm use demo-ui
安装nrm或者使用的时候若报错 code: 'ERR_REQUIRE_ESM'
const open = require('open');
^
Error [ERR_REQUIRE_ESM]: require() of ES Module D:\nodejs\node_global\node_modules\nrm\node_modules\open\index.js from D:\nodejs\node_global\node_modules\nrm\cli.js not supported.
Instead change the require of index.js in D:\nodejs\node_global\node_modules\nrm\cli.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (D:\nodejs\node_global\node_modules\nrm\cli.js:9:14) {
code: 'ERR_REQUIRE_ESM'
若报错如下:
an error occured: Error: EACCES: permission denied, open '/Users/kl/.nrmrc'
则用sudo执行命令,获取权限。
则打开该文件将require改为import重新保存后可成功运行。
3、如果没有创建账户的,可以先创建账户
npm adduser --registry http://1xx.xx.xx:xxxx/
4、然后发布包
npm publish --registry http://1xx.xx.xx:xxxx/
发布成功后,再访问私有仓库地址,就会发现自己的包已经发了上去。
- 具体使用: 新项目中yarn add demo-ui即可。
//全局引用
import xxx from 'demo-ui';
import 'demo-ui/dist/css/index.css';
Vue.use(xxx)
//按需引用
import {Card} from 'demo-ui';
import 'demo-ui/dist/css/card.css';
Vue.use(Card)