写在开头
之前的链接
Monorepo项目管理,vue3+ts+antd+pinia后台管理模板搭建记录(一)
Monorepo项目管理,vue3+ts+antd+pinia后台管理模板搭建记录(二)
包含内容
- ts方法类库打包
- vue3+ts组件库,按需加载打包。均使用rollup,因为不涉及到一些静态资源
- vue3中svg封装
正文
ts方法类库打包
当前项目文件结构如下
── packages
├── components
├── utils
├── project1
└── project2
components为组件库,utils为方法库。
所需依赖
npm i rollup-plugin-typescript2 rollup rollup-plugin-commonjs rollup-plugin-eslint rollup-plugin-node-resolve @typescript-eslint/parser -D
方法库只有ts文件,所以只需要rollup基础依赖和ts依赖,还有eslint校验依赖
tsconfig.js
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "./lib", // 输出目录
"sourceMap": false, // 是否生成sourceMap
"target": "esnext", // 编译目标
"module": "esnext", // 模块类型
"moduleResolution": "node",
"allowJs": false, // 是否编辑js文件
"strict": true, // 严格模式
"noUnusedLocals": true, // 未使用变量报错
"experimentalDecorators": true, // 启动装饰器
"resolveJsonModule": true, // 加载json
"esModuleInterop": true,
"removeComments": false, // 删除注释
"declaration": true, // 生成定义文件
"declarationMap": false, // 生成定义sourceMap
"lib": [
"esnext",
"dom",
"ES2015.promise",
"ES2015"
], // 导入库类型定义
"types": [
"node"
] // 导入指定类型包
},
"include": [
"src/*" // 导入目录
]
}
打包时,rollup-plugin-typescript2插件感觉有点微妙,能用但说不上来,没仔细研究,有些配置好像没有效果。
rollup.config.js
import path from 'path'
import resolve from 'rollup-plugin-node-resolve' // 依赖引用插件
import commonjs from 'rollup-plugin-commonjs' // commonjs模块转换插件
import { eslint } from 'rollup-plugin-eslint' // eslint插件
import ts from 'rollup-plugin-typescript2'
const getPath = _path => path.resolve(__dirname, _path)
import packageJSON from './package.json'
const extensions = [
'.js',
'.ts',
'.tsx'
]
// ts
const tsPlugin = ts({
tsconfig: getPath('./tsconfig.json'), // 导入本地ts配置
extensions
})
// eslint
const esPlugin = eslint({
throwOnError: true,
include: ['src/**/*.ts'],
exclude: ['node_modules/**', 'lib/**']
})
// 基础配置
const commonConf = {
input: getPath('./src/index.ts'),
plugins: [
resolve(extensions),
commonjs(),
esPlugin,
tsPlugin,
]
}
// 需要导出的模块类型
const outputMap = [
{
file: packageJSON.main,
format: 'es',
}
]
const buildConf = options => Object.assign({}, commonConf, options)
export default outputMap.map(output => buildConf({ output: { name: packageJSON.name, ...output } }))
直接引入了package.json里的一些参数,直接导出在dist文件夹下,声明文件也在同级目录。
组件库打包
组件库实现vue3+ts的按需引入
所需依赖
npm i rollup-plugin-esbuild rollup-plugin-css-only rollup-plugin-vue rollup-plugin-scss rollup-plugin-commonjs rollup-plugin-eslint rollup-plugin-node-resolve @rollup/plugin-typescript -D
这边用的ts插件是@rollup/plugin-typescript,因为rpt2在打包vue的时候一直找不到声明文件或者找不到对应module,看了issue问题还是open状态。就直接换了@rollup/plugin-typescript解决问题。
tsconfig.js
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "./", // 输出目录
"sourceMap": false, // 是否生成sourceMap
"target": "esnext", // 编译目标
"module": "esnext", // 模块类型
"moduleResolution": "node",
"allowJs": false, // 是否编辑js文件
"strict": true, // 严格模式
"noUnusedLocals": true, // 未使用变量报错
"experimentalDecorators": true, // 启动装饰器
"resolveJsonModule": true, // 加载json
"esModuleInterop": true,
"removeComments": false, // 删除注释
"declaration": true, // 生成定义文件
"declarationMap": false, // 生成定义sourceMap
"declarationDir": "./",
"lib": [
"esnext",
"dom",
"ES2015.promise",
"ES2015"
], // 导入库类型定义
"types": [
"node"
] // 导入指定类型包
},
"include": [
"vue.d.ts",
"src/*" // 导入目录
],
"exclude": ["node_modules", "es", "lib"]
}
这里include下多加了一个vue.d.ts,这个文件下内容如下。就是声明文件,不然打包时候会报没有module之类的错
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
以及@rollup/plugin-typescript中引入的tsconfig.js在打包时候是起作用的,注意outDir和declarationDir两个输出目录的值。
rollup.config.js
import path from 'path';
import fs from 'fs';
import esbuild from 'rollup-plugin-esbuild';
import css from 'rollup-plugin-css-only';
import vue from 'rollup-plugin-vue';
import scss from 'rollup-plugin-scss';
import commonjs from 'rollup-plugin-commonjs';
import { eslint } from 'rollup-plugin-eslint' // eslint插件
import resolve from 'rollup-plugin-node-resolve' // 依赖引用插件
import typescript from '@rollup/plugin-typescript';
const NOT_COMPS = ['index.ts', 'vue.d.ts'];
let comps = fs.readdirSync('./src');
comps = comps.filter(v => !NOT_COMPS.includes(v));
const inputComps = comps.map(fileName => ({
input: `src/${fileName}/index.ts`,
dir: fileName + '/'
}));
const defaultComps = [{ input: 'src/index.ts', dir: '' }];
const inputs = defaultComps.concat(inputComps);
const getPath = _path => path.resolve(__dirname, _path)
const extensions = [
'.js',
'.ts',
'.tsx',
'.vue'
]
// ts
const tsPlugin = dir =>typescript({
tsconfig: getPath('./tsconfig.json'), // 导入本地ts配置
declaration: dir === ''
})
// eslint
const esPlugin = eslint({
throwOnError: true,
include: ['src/**/*.ts'],
exclude: ['node_modules/**', 'lib/**', 'es/**']
})
// rollup config
export default inputs.map(item => ({
input: getPath(item.input),
output: [
{
name: item.name,
file: `es/${item.dir}index.js`,
format: 'esm'
},
{
name: item.name,
file: `lib/${item.dir}index.js`,
format: 'cjs',
exports: 'named'
}
],
plugins: [
scss(),
css(),
vue({
target: 'browser',
css: false
}),
commonjs(extensions),
esbuild(),
resolve(extensions),
esPlugin,
tsPlugin(item.dir),
],
external: ['vue']
}));
在导入tsconfig的时候多做了一个declaration的判断,配置是按照按需引入做的,所以会对index.ts和每个文件夹都做一次打包,而声明文件只需要在index.ts打包的时候打包就可以了。
不然会导致打包后的结果里存在如下目录
── lib
├── SvgIcon
│ ├── SvgIcon
│ │ └── index.d.ts
│ ├── index.d.ts
│ └── index.ts
├── index.d.ts
└── index.ts
但实际只需要
── lib
├── SvgIcon
│ ├── index.d.ts
│ └── index.ts
├── index.d.ts
└── index.ts
svg封装
封装在了组件库了,使用了vite-plugin-svg-icons插件
vite.config.ts 配置
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
...
plugins: [
...
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), 'src/assets/svg')],
symbolId: 'icon-[dir]-[name]',
customDomId: '__svg__icons__dom__',
}),
],
SvgIcon.vue
<template>
<svg
:height="height"
:width="width"
aria-hidden="true"
>
<use
:href="symbolId"
:fill="color"
:height="height"
:width="width"
/>
</svg>
</template>
<script setup name="SvgIcon" lang="ts">
import { computed } from 'vue'
interface Props {
prefix?: string,
name: string,
color?: string,
height?: string,
width?: string
}
const props = withDefaults(defineProps<Props>(), {prefix: 'icon', color: '#ffffff', height: '16px', width: '16px'})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
项目中使用
需要先安装项目之间的依赖,
pnpm add @test/components -r -F @test/two
<svg-icon
height="20px"
width="20px"
name="usercenter"
color="#333"
/>
<script setup lang="ts">
import { SvgIcon } from '@test/components'
</script>
结束
- gitee store-build分支,保存文章结束时代码状态。
- 基础内容基本搭建好了,组件库,工具库都有。