Vue3 + Typescript + pnpm + rollup/gulp 工程化搭建组件库(一)

7,776 阅读3分钟

Vue3组件库搭建

本项目参考element-plus(更多实现可以去看源码),本项目gitee地址 w-plus

搭建monorepo环境

使用pnpm安装包速度快,磁盘利用率高效,使用pnpm可以快速建立monorepo,所以这里使用pnpm workspace来实现monorepo

创建组件库文件夹w-plus

npm install pnpm -g # 全局安装pnpm
pnpm init -y # 初始化package.json配置文件

修改package.json删除掉无用配置

{
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "WQ",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^4.4.4",
    "vue": "^3.2.20"
  }
}

接着在根目录下创建npm的配置文件.npmrc,增加配置项

shamefully-hoist = true

安装vue3typescript依赖

pnpm install vue@next typescript -D 

如果不添加shamefully-hoist = true配置,会发现node_modules并没有@vue、@babel等依赖包,可以自行试一下,具体参考pnpm官网pnpm

初始化ts,生成配置文件

npx tsc --init # 初始化ts配置文件

tsconfig.json增加如下配置

{
  "compilerOptions": {
    "module": "ESNext", // 打包模块类型ESNext
    "declaration": false, // 默认不要声明文件 
    "noImplicitAny": false, // 支持类型不标注可以默认any
    "removeComments": true, // 删除注释
    "moduleResolution": "node", // 按照node模块来解析
    "esModuleInterop": true, // 支持es6,commonjs模块
    "jsx": "preserve", // jsx 不转
    "noLib": false, // 不处理类库
    "target": "es6", // 遵循es6版本
    "sourceMap": true,
    "lib": [ // 编译时用的库
      "ESNext",
      "DOM"
    ],
    "allowSyntheticDefaultImports": true, // 允许没有导出的模块中导入
    "experimentalDecorators": true, // 装饰器语法
    "forceConsistentCasingInFileNames": true, // 强制区分大小写
    "resolveJsonModule": true, // 解析json模块
    "strict": true, // 是否启动严格模式
    "skipLibCheck": true // 跳过类库检测
  },
  "exclude": [ // 排除掉哪些类库
    "node_modules",
    "**/__tests__",
    "w-plus/**"
  ]
}

根目录增加配置文件pnpm-workspace.yaml添加如下配置,具体可参考pnpm-workspace.yaml

packages: 
  - 'packages/**' # 存放编写的组件的
  - play 

目录结构为

    + node_modules
    + packages # 存放组件代码
    + play # 测试组件
    - .npmrc 
    - .packages.json
    - .pnpm-lock.yaml
    - .pnpm-workspace.yaml
    - .tsconfig.json

接下来在play目录下npm init生成package.json

{
  "private": true,
  "name": "@w-plus/play",
  "scripts": {
    "dev": "vite"
  },
  "author": "WQ",
  "license": "ISC",
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.9.3",
    "vite": "^2.6.10"
  }
}

然后安装依赖

pnpm install vite @vitejs/plugin-vue -D # 使用vite来搭建vue环境

play目录下创建vite的配置文件vite.config.js

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [vue()],
});

接着创建index.htmlapp.vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script src="./main.ts" type="module"></script>
</body>
</html>
<template>
    测试
</template>

创建入口文件main.ts

import { createApp } from "vue"
import App from './app.vue'

const app = createApp(App);
app.mount('#app')

# './app.vue' ts报错
已声明“App”,但从未读取其值。ts(6133)
找不到模块“./app.vue”或其相应的类型声明。ts(2307)

为了解决这个问题,需要给app.vue声明一个模块表示类型

在根目录下创建typings目录新建文件vue-shim.d.ts

declare module '*.vue'{
    import type { DefineComponent } from "vue";  # 导入vue官方组件type
    const component:DefineComponent<{},{},any>
    export default component
}

play目录下的package.json增加脚本

...
"scripts": {
    "dev": "vite"
  },
...

启动项目测试一下,执行脚本npm run dev启动服务http://localhost:3000/访问地址后看到app.vue中的内容

因为当前是在play目录下运行的,我们一般肯定是在最外层运行,所以我们要在根目录下的package.json增加脚本

...
"scripts": {
    "dev": "pnpm -C play dev"  # 执行play下的dev脚本
  },
...

然后运行pnpm run dev这时候可以看到运行play目录下的dev脚本成功,同刚才的效果

到此,就完成了基础的测试环境搭建,接下来在根目录packages下搭建组件部分


后续见下一章节:组件搭建