Skip to content

创建项目

初始化

(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;