1-umi-前端工程化搭建

vscode 插件推荐

  • eslint
  • prettier
  • typescript
  • GitLens

创建项目文件夹

  • mkdir umi-monorepo
  • cd umi-monorepo
  • pnpm init -y 初始化项目配置

创建基础目录结构

txt 复制代码
umi-monorepo/
├── packages/  项目目录
├── examples/  示例项目目录
└── scripts/   脚本目录

根目录下创建pnpm-workspace.yaml文件

yaml 复制代码
packages:
  # 包目录
  - 'packages/*'
  # 示例项目目录
  - 'examples'

根目录下创建 .gitignore文件

txt 复制代码
# Dependencies
node_modules/
.pnpm-store/

# Build outputs
dist/
lib/
es/

# Environment files
.env
.env.local

# IDE files
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Logs
*.log

创建Typescript项目

  • 安装: pnpm i -Dw typescript
  • 初始化TS配置: pnpm tsc --init
    • 生成一个 tsconfig.base.json 文件
json 复制代码
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",// 指定模块解析策略
    "noEmit": false,// 不生成任何文件
    "allowJs": true,// 允许编译 js 文件
    "skipLibCheck": true,// 跳过库文件的类型检查
    "esModuleInterop": true,// 允许从没有设置默认导出的模块中默认导入
    "experimentalDecorators": true,// 允许使用实验性的装饰器
    "strict": true,// 启用所有严格类型检查选项
    "forceConsistentCasingInFileNames": true,// 禁止对同一个文件的不一致的引用
    "noImplicitReturns": true,// 在所有函数中,返回值类型必须与函数的返回值类型一致
    "declaration": true,// 生成相应的.d.ts文件
    "resolveJsonModule": true// 允许从 json 文件中导入数据
  },
  "exclude": ["node_modules", "lib"]
}

prettier: 代码格式化

  • 安装: pnpm i -Dw prettier
    • -Dw: 安装依赖并保存到根目录下package.json devDependencies 中
  • 根目录下创建 .prettierrc文件
  • 安装依赖:pnpm i -Dw prettier-plugin-organize-imports prettier-plugin-packagejson
    • prettier-plugin-organize-imports: 插件,自动排序 import
    • prettier-plugin-packagejson: 插件,格式化 package.json(专用于标准化 package.json 文件的属性顺序)
json 复制代码
{
  "printWidth": 80,// 每行字符数
  "singleQuote": true,// 使用单引号
  "trailingComma": "none",// 对象字面量中的最后一个属性的结尾添加逗号
  "proseWrap": "never",// 当行字符数超过 printWidth 时,换行方式,默认为 hard wrap,可选值:never | always | preserve
  "overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }],
  "plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"]// 格式化时候引入的插件
}

.prettierignore: 忽略需要格式化的文件

txt 复制代码
node_modules/
lib/
dist/
coverage/
pnpm-lock.yaml

package.json添加格式化脚本

json 复制代码
{
  "scripts": {
    "format": "prettier --write .",// 格式化所有文件
    "format:check": "prettier --check ."// 检查所有文件是否格式化
  }
}
  • 测试命令
    • pnpm format: 格式化所有文件
    • pnpm format:check:检查所有文件是否格式化

ESLint: 代码规范(这个现在也可以用oxlint代替)

  • 安装: pnpm i -Dw eslint@8.45.0
  • 根目录下创建:.eslinrc.js文件,配置如下:
txt 复制代码
module.exports = {
  'root': true, // 根目录
  'parser': '@typescript-eslint/parser',// 指定解析器
  'plugins': ['@typescript-eslint'],// 指定插件
  'rules': {
    'no-var': 'error',// 不能使用var声明变量
    'no-extra-semi': 'error',// 禁止不必要的分号
    '@typescript-eslint/indent': ['error', 2],// 缩进2个空格
    'import/extensions': 'off',// 导入文件时,忽略扩展名
    'linebreak-style': [0, 'error', 'windows'],// 换行符使用\r\n
    'indent': ['error', 2, { SwitchCase: 1 }], // error类型,缩进2个空格
    'space-before-function-paren': 0, // 在函数左括号的前面是否有空格
    'eol-last': 0, // 不检测新文件末尾是否有空行
    'semi': ['error', 'always'], // 在语句后面加分号
    'quotes': ['error', 'single'],// 字符串使用单双引号,double,single
    'no-console': ['error', { allow: ['log', 'warn'] }],// 允许使用console.log()
    'arrow-parens': 0,// 箭头函数参数是否使用括号
    'no-new': 0,//允许使用 new 关键字
    'comma-dangle': [2, 'never'], // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,always-multiline多行模式必须带逗号,单行模式不能带逗号
    'no-undef': 0// 不能有未定义的变量
  },
  'parserOptions': {// 解析器配置
    'ecmaVersion': 6,// ECMAScript版本
    'sourceType': 'module',// 模块类型
    'ecmaFeatures': {// 特性配置
      'modules': true// 支持模块
    }
  }
};

安装typescript-eslint

  • pnpm i -Dw @typescript-eslint/eslint-plugin@6.2.0 @typescript-eslint/parser@6.2.0

添加eslint脚本

json 复制代码
{
  "scripts": {
    "lint": "eslint packages/**/*.{ts,tsx,js,jsx} examples/**/*.{ts,tsx,js,jsx} --fix --no-error-on-unmatched-pattern",
    "lint:check": "eslint packages/**/*.{ts,tsx,js,jsx} examples/**/*.{ts,tsx,js,jsx} --no-error-on-unmatched-pattern"
  }
}
  • 测试命令:pnpm lint:check

git: 提交规范(commitlint)

安装commitlint

  • pnpm i -Dw @commitlint/cli @commitlint/config-conventional

根目录初始化配置文件

  • pnpm commitlint --init-> 出现 commitlint.config.js文件,修改内容如下:
js 复制代码
module.exports = {extends: ['@commitlint/config-conventional']}

安装commitizen(可选)

  • 帮助生成规范的提交信息
  • pnpm i -Dw commitizen cz-conventional-changelog
  • 修改package.json文件
json 复制代码
{
  "scripts": {
    "commit": "git cz"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

安装husky

  • 用来检测git提交信息
  • 安装: pnpm i -Dw husky
  • 初始化 husky
txt 复制代码
# 初始化husky
pnpm exec husky init
# 初始化后会生成一个 .husky文件夹

# 设置prepare脚本,确保其他人clone后也能自动安装hooks
npm pkg set scripts.prepare="husky install"

.husky在添加commit-msg钩子(文件): 用来检测提交信息

txt 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm exec commitlint --edit $1
  • 安装:lint-staged -> 用于在提交前检查代码格式
  • pnpm i -Dw lint-staged
  • 修改package.json文件
json 复制代码
{
  "lint-staged": {// 添加lint-staged配置
    "*.{ts,tsx,js,jsx}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{json,md}": [
      "prettier --write"
    ]
  }
}
  • 在根目录创建.husky/pre-commit文件,内容如下:
txt 复制代码
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm lint:check // 这里就是commit前执行package.json中的这个lint:check命令
  • 提交代码时候
    • pre-commit hook 会运行 pnpm lint:check
      • 如果 lint:check 成功,则 git commit
    • commit-msg hook 会验证提交信息是否符合 conventional commit 格式(通过 commitlint)
      • 如果 commitlint 验证通过,则 git commit

Father: 构建工具

  • 用来构建项目,支持多包管理,支持monorepo
  • 安装:pnpm i -w father
  • 根目录创建.father.config.ts文件,内容如下:
ts 复制代码
import { defineConfig } from 'father';

export default defineConfig({// 这里是father的配置
  cjs: {// cjs配置
    output: 'lib',// 输出目录
  },
});

changesets版本管理

  • 用来管理版本,支持monorepo
  • 安装:pnpm i -Dw @changesets/cli
  • 初始化:pnpm exec changeset init -> 创建.changeset文件夹
  • 后面在package.json中添加版本管理相关scripts

进入exmaples目录

  • 我们开始试验一下
  • 执行:pnpm dlx create-umi@latest
  • 创建 .umirc.ts
  • 创建成功,cd ..,进入根目录
ts 复制代码
import { defineConfig } from '@umijs/max';

export default defineConfig({
  antd: {},
  access: {},
  model: {},
  initialState: {},
  request: {},
  layout: {
    title: 'Umi Examples',
  },
  routes: [
    { path: '/', redirect: '/home' },
    { name: '首页', path: '/home', component: './Home' },
  ],
  npmClient: 'pnpm',
  plugins: [
    // 这里将会添加我们以后开发的插件
  ],
});

整个项目目录

txt 复制代码
umi-plugins-monorepo/
├── .husky/                  # git hooks
│   ├── commit-msg
│   └── pre-commit
├── examples/                # 示例项目
│   ├── src/
│   ├── .umirc.ts
│   └── package.json
├── packages/                # 插件包目录
│   └── tsconfig.base.json
├── scripts/                 # 脚本目录
├── .eslintrc.js            # ESLint配置
├── .fatherrc.base.ts       # Father构建配置
├── .gitignore              # Git忽略文件
├── .prettierrc             # Prettier配置
├── .prettierignore         # Prettier忽略文件
├── commitlint.config.js    # Commitlint配置
├── package.json            # 根package.json
├── pnpm-workspace.yaml     # pnpm workspace配置

整个项目的package.json文件如下:

json 复制代码
{
  "name": "umi-monorepo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "directories": {
    "example": "examples"
  },
  "scripts": {
    "commit": "git cz",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "lint": "eslint packages/**/*.{ts,tsx,js,jsx} examples/**/*.{ts,tsx,js,jsx} --fix --no-error-on-unmatched-pattern",
    "lint:check": "eslint packages/**/*.{ts,tsx,js,jsx} examples/**/*.{ts,tsx,js,jsx} --no-error-on-unmatched-pattern",
    "prepare": "husky install"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  },
  "lint-staged": {
    "*.ts": [
      "eslint --fix",
      "git add"
    ]
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@changesets/cli": "^2.29.5",
    "@commitlint/cli": "^19.8.1",
    "@commitlint/config-conventional": "^19.8.1",
    "@typescript-eslint/eslint-plugin": "6.2.0",
    "@typescript-eslint/parser": "6.2.0",
    "@umijs/lint": "4.4.2",
    "commitizen": "^4.3.1",
    "cz-conventional-changelog": "^3.3.0",
    "eslint": "8.45.0",
    "husky": "^9.1.7",
    "lint-staged": "^16.1.2",
    "prettier": "^3.6.2",
    "prettier-plugin-organize-imports": "^4.2.0",
    "prettier-plugin-packagejson": "^2.5.19",
    "typescript": "^5.8.3"
  },
  "dependencies": {
    "father": "^4.6.1"
  }
}
相关推荐
真夜2 小时前
关于对echart盒子设置百分比读取的宽高没有撑开盒子解决方案
前端
楠木6852 小时前
RAG 资料库 Demo 完整开发流程
前端·ai编程
肠胃炎2 小时前
挂载方式部署项目
服务器·前端·nginx
像我这样帅的人丶你还2 小时前
使用 Next.js + Prisma + MySQL 开发全栈项目
前端
FPGA小迷弟2 小时前
FPGA 时序约束基础:从时钟定义到输入输出延迟的完整设置
前端·学习·fpga开发·verilog·fpga
毛骗导演3 小时前
@tencent-weixin/openclaw-weixin 插件深度解析(四):API 协议与数据流设计
前端·架构
毛骗导演3 小时前
@tencent-weixin/openclaw-weixin 插件深度解析(二):消息处理系统架构
前端·架构
IT_陈寒3 小时前
深入理解JavaScript:核心原理与最佳实践
前端·人工智能·后端
MrGud3 小时前
Cesium中的坐标系及其转换
前端·cesium