创建项目
初始化
(1) 创建package.json
bash
pnpm init- 修改为
json
{
"name": "vue3-my-component",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.15.1" // 你自己的pnpm 版本
}(2) 根目录 创建pnpm-workspace.yaml
yaml
packages:
- "packages/*"
- "site/*"
- "!**/test/**"(3) 架构
bash
├── package.json
├── pnpm-workspace.yaml
├── packages
│ ├── utils
│ │ ├── package.json
│ │ ├── tsconfig.json
│ ├── ui
│ │ ├── package.json
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ ├── vite.config.bundle.style.ts
│ │ ├── vite.config.bundle.ts
│ │ ├── vite.config.style.ts
│ │ ├── vite.config.ts
│ │ ├── scripts
│ │ ├── src
│ │ │ ├── index.ts
│ │ │ ├── components.ts
│ │ │ ├── style.ts
│ │ │ ├── button
│ │ │ │ ├── button.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── style
│ │ │ │ │ ├── index.less
│ │ │ │ │ ├── index.ts(4) 初始化两个package.json
- cd 到packages/ui
bash
pnpm init(2) package.json
json
{
"name": "@vue3-my-component/ui",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.15.1"
}- cd 到packages/utils
bash
pnpm init(2) package.json
json
{
"name": "@vue3-my-component/utils",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.15.1"
}(5) 引入less
- packages/ui/src/button/style/index.ts
ts
import "./index.less";(6) 安装vite 和 ts
- 根目录下面 每个包的目录下面都安装vite 和 ts
bash
pnpm add vite vitest typescript -r -D(7) 安装eslint
- 根目录 安装eslint和prettier
bash
pnpm add eslint @mistjs/eslint-config-vue -D -w- 根目录新建 .eslintrc.js
js
module.exports = {
extends: ["@mistjs/eslint-config-vue"],
};(8) 配置ts
- 安装
bash
pnpm add @vue/tsconfig -r -D- 根目录下面新建 tsconfig.json
json
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"isolatedModules": true,
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom", "dom.iterable", "scripthost"],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {}
}
}- packages/ui/tsconfig.json
json
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}- packages/ui/tsconfig.app.json
json
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": "."
}
}- packages/ui/tsconfig.node.json
json
{
"extends": "@tsconfig/node24/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}- packages/utils/tsconfig.json
json
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"isolatedModules": true,
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom", "dom.iterable", "scripthost"],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {}
}
}(9) 安装vue
bash
pnpm add vue -r(10) 安装 packages/ui/src/components.ts
ts
export { default as Button } from "./button";(11) 安装 packages/ui/src/index.ts
ts
import type { App } from "vue";
import * as components from "./components";
export * from "./components";
export default {
install(app: App) {
for (const component in components) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const Comp = components[component];
if (Comp.install) app.use(Comp);
}
return app;
},
};(12) 安装 packages/ui/src/style.ts
ts
import "./button/style";(13) 安装 packages/ui/src/button/button.vue
vue
<script setup lang="ts">
defineOptions({
name: "LButton",
});
</script>
<template>
<button>点击我</button>
</template>
<style scoped></style>(14) 安装 packages/ui/src/button/index.ts
ts
import Button from "./button.vue";
import type { App, Plugin } from "vue";
// 按需引入
Button.install = (app: App) => {
app.component(Button.name as string, Button);
return app;
};
export default Button as typeof Button & Plugin;