使用 Turborepo 构建前端项目
什么是 Turborepo
Turborepo 是一个用于构建和打包前端项目的工具,它可以帮助你更快地构建和打包项目,同时还可以帮助你更好地管理项目的依赖关系。
如何使用 Turborepo
根目录下面新建文件
turbo.json
json
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": [
"$TURBO_DEFAULT$",
"!{dist,build,coverage,.turbo}/**",
"!**/*.md",
"!**/*.test.{ts,tsx,js,jsx}"
],
"outputs": ["dist/**", ".vitepress/dist/**"],
"cache": true
},
"dev": {
"dependsOn": ["^build"],
"cache": false,
"persistent": true
},
"preview": {
"dependsOn": ["build"],
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": true
},
"lint:fix": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": false,
"outputs": []
},
"lint:style": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": true
},
"lint:style:fix": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": false,
"outputs": []
},
"format": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": false,
"outputs": []
},
"format:check": {
"dependsOn": [],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"cache": true
},
"test": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", "!{dist,build,coverage,.turbo}/**"],
"outputs": ["coverage/**"],
"cache": true
},
"clean": {
"cache": false
}
},
"globalDependencies": [
".env",
".env.*",
"tsconfig.json",
"tsconfig.*.json",
"eslint.config.js",
".prettierrc",
".stylelintrc.json",
"vite.config.ts"
],
"globalEnv": ["NODE_ENV", "CI"]
}build 文件夹
- 打包最重要的文件
初始化
bash
pnpm init修改 package.json
json
{
"name": "@tscomponents/build-config",
"version": "1.0.0",
"type": "module",
"private": true,
"main": "./build.config.ts",
"types": "./build.config.ts",
"exports": {
".": "./build.config.ts"
},
"scripts": {
"test": "echo test",
"clean": "rimraf .turbo",
"lint": "eslint . --ext .js,.ts",
"lint:fix": "eslint . --ext .js,.ts --fix",
"format": "prettier --write \"**/*.{js,ts,json}\"",
"format:check": "prettier --check \"**/*.{js,ts,json}\""
},
"peerDependencies": {
"vite": ">=3.0.0",
"vue": ">=3.3",
"vite-plugin-dts": "^4.5.4"
},
"peerDependenciesMeta": {
"vue": {
"optional": true
}
},
"dependencies": {},
"devDependencies": {}
}解释说明
peerDependencies在安装包之前 必须安装的依赖peerDependenciesMeta如果没有安装前置vue,则会警告 但是不报错
build文件夹下面
- build.config.ts
ts
import vue from "@vitejs/plugin-vue";
import { type UserConfig } from "vite";
import dts from "vite-plugin-dts";
/**
* 构建配置选项
*/
interface BuildOptions {
name?: string; // 库名称(UMD 格式使用)
entry?: string; // 入口文件路径
external?: string[]; // 外部依赖(不打包)
globals?: Record<string, string>; // UMD 格式的全局变量映射
preserveModules?: boolean; // 是否保留模块结构(ES 格式)
}
/**
* 通用的 Vite 开发服务器配置
*/
const commonServerConfig = {
host: "0.0.0.0", // 监听所有网络接口
strictPort: false, // 端口被占用时自动尝试下一个可用端口
};
/**
* 生成 Vue 组件库的构建配置
* 用于打包 Vue 组件,生成单文件 ES 和 UMD 格式
*/
export function generateVueConfig(options: BuildOptions = {}): UserConfig {
const {
name = "Library",
entry = "./src/index.ts",
external = [],
globals = {},
} = options;
return {
server: commonServerConfig,
plugins: [
vue() as any, // Vue 3 单文件组件支持
dts({
tsconfigPath: "./tsconfig.build.json", // TypeScript 配置文件
outDir: "dist", // 类型声明文件输出目录
cleanVueFileName: true, // 清理 Vue 文件名
copyDtsFiles: true, // 复制已存在的 .d.ts 文件
rollupTypes: true, // 合并所有类型声明为单个文件
}),
],
build: {
lib: {
entry, // 入口文件
name, // 库的全局变量名(UMD 格式)
formats: ["es", "umd"], // 输出格式:ES Module 和 UMD
fileName: (format) => `index.${format === "es" ? "js" : "umd.js"}`, // 文件名规则
},
rollupOptions: {
external: ["vue", ...external], // 不打包 Vue 和其他外部依赖
output: {
globals: {
vue: "Vue", // Vue 的全局变量名
...globals,
},
exports: "named", // 使用命名导出
assetFileNames: (assetInfo) => {
if (assetInfo.name?.endsWith(".css")) return "index.css"; // CSS 文件统一命名
return assetInfo.name || "";
},
},
},
cssCodeSplit: false, // 不分割 CSS
outDir: "dist", // 输出目录
},
};
}
/**
* 生成普通库的构建配置
* 支持保留模块结构(tree-shaking 友好)或单文件打包
*/
export function generateConfig(options: BuildOptions = {}): UserConfig {
const {
name = "Library",
entry = "./src/index.ts",
external = [],
globals = {},
preserveModules = true, // 默认保留模块结构
} = options;
if (!preserveModules) {
// 单文件模式:所有代码打包成一个文件
return {
server: commonServerConfig,
plugins: [
dts({
tsconfigPath: "./tsconfig.build.json", // TypeScript 配置
outDir: "dist", // 类型声明输出目录
copyDtsFiles: true, // 复制已存在的 .d.ts 文件
rollupTypes: true, // 合并类型声明
}),
],
build: {
lib: {
entry,
name,
formats: ["es", "umd"], // ES 和 UMD 格式
fileName: (format) => `index.${format === "es" ? "js" : "umd.js"}`,
},
rollupOptions: {
external, // 外部依赖
output: {
globals, // UMD 全局变量映射
exports: "named", // 命名导出
},
},
outDir: "dist",
},
};
}
// 保留模块结构模式:每个源文件对应一个输出文件,支持 tree-shaking
return {
server: commonServerConfig,
plugins: [
dts({
tsconfigPath: "./tsconfig.build.json", // TypeScript 配置
outDir: "dist/es", // 类型声明输出到 ES 目录
copyDtsFiles: false, // 不复制文件,而是生成新的
rollupTypes: false, // 不合并类型声明,保持模块结构
entryRoot: "src", // 源码根目录
insertTypesEntry: true, // 自动插入 types 入口
include: ["src/**/*"], // 包含所有源文件
}),
],
build: {
lib: {
entry, // 入口文件
name, // UMD 格式的全局变量名
formats: ["es", "umd"], // 输出 ES 和 UMD 两种格式
},
rollupOptions: {
external, // 不打包的外部依赖
output: [
// ES 格式:保留模块结构,支持按需引入
{
format: "es",
dir: "dist/es", // 输出到 dist/es 目录
entryFileNames: "[name].mjs", // 文件名保持原样,扩展名 .mjs
preserveModules: true, // 保留模块结构
preserveModulesRoot: "src", // 保留的根目录
exports: "named", // 命名导出
},
// UMD 格式:单文件打包,用于浏览器直接引入
{
format: "umd",
dir: "dist/umd", // 输出到 dist/umd 目录
entryFileNames: `${name.toLowerCase()}.umd.js`, // 单个 UMD 文件
name, // 全局变量名
globals, // 外部依赖的全局变量映射
exports: "named", // 命名导出
},
],
},
},
};
}说明
必须保证每个分包下面有src/index.ts入口文件,否则会报错
每个分包下面 都必须有个
tsconfig.build.json文件
格式如下
json
{
"extends": "../../tsconfig.src.json",
"compilerOptions": {
"rootDir": ".",
"baseUrl": "./",
"outDir": "./dist"
},
"include": ["src"]
}