[Talk is cheap. Show me the code]
使用背景:
当公司出现多个系统,多个系统之间需要进行跳转组件时,因此需要一个跳转的导航组件,而在各个业务系统中都维护一个业务组件耗时耗力,因此将这种公共业务组件做成一个npm包的形式,发布到公司私有的gitlab上,公司内部代码切记不要发布到公网,其他业务系统只需要按需下载即可。
1.使用vite创建一个vue3项目并做相关配置
在工具上你可以选择其他工具,当然也会遇到一些其他可能会出现的问题,如果你不愿意重复的去造轮子,完全可以跟我选择一样的工具,你需要保证自己了解这些工具的基本使用,你需要用到的工具(‘/’为或的意思)有:
nvm/n
yarn/npm/pnpm
vite
vue3
element-plus
ts
1.1 创建一个vue3项目并进行相关配置
yarn create @vitejs/app //选择自己的framework&variant 内容参考见下图
cd bc //这里根据自己的项目名称进行切换
yarn
1.2 进行相关的代码配置
这里请根据自己的需要进行相关的修改,相关参数请翻阅对应的文档,我们需要做的配置有:
1:eslint配置 ESLint相关配置实现
2:vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
// import path from 'path';
// import { resolve } from 'path'
const path = require('path')
function _resolve(dir: string) {
return path.resolve(__dirname, dir);
}
export default env => {
return defineConfig({
plugins: [
vue(),
],
css: {
preprocessorOptions: {
scss: {
prependData: '@use "@/assets/style/element/index.scss" as *;'
}
}
},
resolve: {
alias: {
'@': _resolve('src'),
'@assets': _resolve('src/assets'),
'@comps': _resolve('src/components'),
},
extensions: ['', '.ts', '.tsx', '.js', '.scss'],
},
server: {
open: true, // 自开启浏览器
host: '0.0.0.0', // fix use `--host` to expose
// disableHostCheck: true,
https: true,
proxy: {
}
},
esbuild: false,
build: {
lib: {
entry: _resolve('src/index.ts'),
name: 'app',
fileName: (format) => `app.${format}.js`
},
terserOptions: {
compress: {
keep_infinity: true,
// 删除console
drop_console: true
}
},
// 禁用该功能可能会提高大型项目的构建性能
brotliSize: false,
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
});
};
3:tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["element-plus/global"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
// "extends": "./tsconfig.node.json"
}
4:package.json
{
"name": "**自行决定",
"private": true,
"version": "0.0.1",
"author": {
"name": "st77"
},
"files": [
"dist"
],
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit --skipLibCheck && vite build",
"preview": "vite preview"
},
"module": "./dist/app.es.js",
"main": "./dist/app.umd.js",
"exports": {
".": {
"import": "./dist/app.es.js",
"require": "./dist/app.umd.js"
},
"./dist/style.css": {
"import": "./dist/style.css",
"require": "./dist/style.css"
}
},
"keywords": [
"mtbc"
],
"dependencies": {
"element-plus": "^2.0.1",
"path": "^0.12.7",
"vue": "^3.2.25",
"@wefly/vue-virtual-scroller": "^1.0.5",
"axios": "^0.21.1",
"lodash": "^4.17.21",
"vue-clipboard3": "^1.0.1",
"vue-router": "^4.0.5",
"vuex": "^4.0.0"
},
"devDependencies": {
"@types/node": "^17.0.17",
"@vitejs/plugin-vue": "^2.2.0",
"typescript": "^4.5.4",
"vite": "^2.8.0",
"vue-tsc": "^0.29.8",
"@ehutch79/vite-eslint": "0.0.1",
"@vue/compiler-sfc": "^3.0.5",
"@vue/eslint-config-prettier": "^6.0.0",
"autoprefixer": "^10.2.5",
"babel-eslint": "^10.1.0",
"crypto-js": "^4.0.0",
"element-plus": "^1.3.0-beta.5",
"eslint": "^6.7.2",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^7.0.0-0",
"extract-text-webpack-plugin": "^3.0.0",
"husky": "^1.3.1",
"lint-staged": "^9.5.0",
"mockjs": "^1.1.0",
"prettier": "^1.19.1",
"sass": "^1.41.1",
"vite-plugin-mock": "^2.3.0",
"vite-plugin-svg-icons": "^0.4.0"
}
}
2、编写代码并在本地进行调试
2.1 编写你需要的组件并导出
我这里编写了一个app-nav组件,请保证你的文件路径正确,示例如下:
app-nav.vue
<template>
<el-dropdown trigger="click">
<span class="el-dropdown-link">
{{ activeApp ? activeApp : apps[0] }}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="app in apps " :key="app" @click="pinkApp(app)">{{ app }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, ref, watch, onMounted } from 'vue';
import { ArrowDown } from '@element-plus/icons-vue'
interface Test {
apps: string[],
pinkApp: any,
activeApp: string,
}
export default defineComponent({
components: {
ArrowDown
},
props: {
},
setup(props, context) {
const state = reactive<Test>({
apps: ['Action', 'Action2', 'Action3', 'Action4', 'Action5'],
activeApp: '',
pinkApp(app: any) {
state.activeApp = app
}
})
return {
...toRefs(state)
};
}
})
</script>
<style scoped>
.example-showcase .el-dropdown-link {
cursor: pointer;
color: var(--el-color-primary);
display: flex;
align-items: center;
}
</style>
这里index.ts路径需要跟vite.config.ts中的路径保持一致
index.ts
export { default as AppNav } from './app-nav/index.vue';
本地调试正常之后,推上到你的私有gitlab仓库,推送到npm库请参考发布npm到公共仓库
3、在其他项目中使用
在你要使用的项目package.json中添加你的包名称:git+对应的仓库地址。你可以定义任何符合需要的名称
"mtbc": "git+https://gitlab.***.com/**/MtBc.git",
npm i / yarn 在页面中使用即可
3、代码编写过程中可能出现的问题
1:element-plus Cannot find name 'Language'. 报错 解决方案修改build命令
# --skipLibCheck 忽略所有的声明文件( `*.d.ts`)的类型检查。
# --noEmit 不生成输出文件。
"build": "vue-tsc --noEmit --skipLibCheck && vite build",
2:An import path cannot end with a '.ts' extension. Consider importing '@/index.js' instead. 解决方案:
目前排查是ts/node版本导致的,所以我将node版本选择在v14.17.0,重新构建了一遍项目,解决了问题。
如果有任何关于本文的意见,欢迎在文章下方留言,我会在看到的第一时间回复。