在培训结束后, 通过对轮播图组件的重写, 掌握了vue 3 组件库的开发过程, 特写此片文章总结
1 技术栈
简述下选择的技术栈及选择它们的理由
- vite: dev启动速度极快, 非常适合开发调试
- rollup: 更优秀的打包工具, 不过只适用于纯js/ts文件, 对于有静态资源文件的, 还是使用webpack打包更好
- Vue 3: 组合式api真的很好用
- TypeScript: 强类型/把一部分错误在编译器暴露出来, 一定是优势大于麻烦
- TSX: 暂时不明, 但可以脱离template, 使用render函数
2 创建组件库模板
使用vite创建项目, 官方文档
利用vue-ts模板:
pnpx create-vite vue-component-template --template vue-ts
如果需要更复杂的模板, 例如使用vuex
/vue-router
, 需要使用degit
工具, 从社区维护模板中寻找合适的项目, 具体内容参照官方文档
创建完成后, 需要对项目进行一些修改:
2.1 增加eslint和prettier进行代码检查
在package.json
的devDependencies
中增加如下依赖:
{
"eslint": "^7.32.0",
"eslint-plugin-import": "^2.24.1",
"eslint-plugin-vue": "~7.16.0",
"@typescript-eslint/eslint-plugin": "~4.29.3",
"@typescript-eslint/parser": "~4.29.3",
"@vue/eslint-config-standard": "~6.1.0",
"@vue/eslint-config-typescript": "~7.0.0",
"prettier": "^2.3.2"
}
在根目录增加eslint配置文件.eslintrc.js
:
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
env: {
node: true,
},
parserOptions: {
ecmaVersion: 2020,
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'space-before-function-paren': ['error', 'never'],
'comma-dangle': ['error', 'only-multiline'],
}
}
在根目录增加eslint忽略文件.eslintignore
:
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
.eslintrc.js
prettier.config.js
/src/mock/*
/lib
在根目录增加prettier配置文件.prettierrc
:
{
"trailingComma": "none",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 100
}
在根目录增加prettier忽略文件.prettierignore
:
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
/lib/**
2.2 修改目录结构
将src
修改为examples
, 用它作为组件的示例工程
修改index.html
, 将/src/main.ts
调整为/examples/main.ts
:
<body>
<div id="app"></div>
<script type="module" src="/examples/main.ts"></script>
</body>
新建目录packages
, 作为组件的根目录
修改tsconfig.json
, 调整ts的编译文件:
{
"include": ["packages/**/*.ts", "packages/**/*.d.ts", "packages/**/*.tsx", "packages/**/*.vue"]
}
2.3 增加TSX支持
vite默认不支持tsx, 需安装@vitejs/plugin-vue-jsx
:
pnpm add -D @vitejs/plugin-vue-jsx
在vite.config.js中使用:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()]
});
2.4 使用rollup打包
在package.json
的devDependencies
中增加如下依赖:
{
"@babel/core": "^7.15.0",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-node-resolve": "^13.0.4",
"@rollup/plugin-typescript": "^8.2.5",
"@vue/babel-plugin-jsx": "^1.0.6"
}
使用babel处理tsx打包的问题, 增加配置文件.babelrc
:
{
"plugins": [["@vue/babel-plugin-jsx"]]
}
在根目录创建rollup.config.js
:
import typescript from '@rollup/plugin-typescript';
import babel from '@rollup/plugin-babel';
import { name } from './package.json';
export default {
input: './packages/index.tsx',
output: {
name,
dir: 'lib',
format: 'es',
globals: {
vue: 'Vue'
}
},
external: ['vue'],
plugins: [
typescript(),
babel({ babelHelpers: 'bundled', extensions: ['.ts', '.js', '.tsx'] })
]
};
修改package.json
中的相关配置:
{
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"dev": "vite",
"build": "rollup -c",
"serve": "vite preview"
}
}
执行pnpm build
即可在lib
目录下看到打包后的文件
3 小坑
3.1 TypeScript的类型声明文件
需要修改tsconfig.json
:
{
"compilerOptions": {
"declaration": true,
"declarationDir": "lib"
}
}
3.2 组件全局注册时的类型问题
编写tsx组件时, 最后的类型声明文件很可能不存在install方法的定义, 增加了一个处理工具类componentUtil.ts
:
import { App, Plugin } from 'vue';
const withInstall = <T>(comp: T): T & Plugin => {
const c = comp as any;
c.install = function(app: App) {
app.component(c.name, comp);
};
return comp as T & Plugin;
};
export default {
withInstall
};
修改组件的index.tsx
:
import { defineComponent } from 'vue';
import ComponentUtil from './utils/ComponentUtil';
export default ComponentUtil.withInstall(
defineComponent({
setup() {
return () => <div>Vue 3 Custom Component Template</div>;
}
})
);