<返回目录     Powered by claud/xia兄

第14课: 配置与工程化

tsconfig.json基础配置

{
  "compilerOptions": {
    // 编译目标
    "target": "ES2020",

    // 模块系统
    "module": "commonjs",

    // 输出目录
    "outDir": "./dist",

    // 源码目录
    "rootDir": "./src",

    // 生成声明文件
    "declaration": true,

    // 生成source map
    "sourceMap": true,

    // 严格模式
    "strict": true
  },

  // 包含的文件
  "include": ["src/**/*"],

  // 排除的文件
  "exclude": ["node_modules", "dist"]
}

编译选项详解

{
  "compilerOptions": {
    /* 语言和环境 */
    "target": "ES2020",                    // 编译目标版本
    "lib": ["ES2020", "DOM"],              // 包含的库文件
    "jsx": "react",                        // JSX支持
    "experimentalDecorators": true,        // 启用装饰器
    "emitDecoratorMetadata": true,         // 装饰器元数据

    /* 模块 */
    "module": "commonjs",                  // 模块系统
    "moduleResolution": "node",            // 模块解析策略
    "baseUrl": "./",                       // 基础路径
    "paths": {                             // 路径映射
      "@/*": ["src/*"],
      "@utils/*": ["src/utils/*"]
    },
    "resolveJsonModule": true,             // 导入JSON

    /* 输出 */
    "outDir": "./dist",                    // 输出目录
    "rootDir": "./src",                    // 源码目录
    "removeComments": true,                // 移除注释
    "noEmit": false,                       // 不生成文件
    "declaration": true,                   // 生成.d.ts
    "declarationMap": true,                // 生成.d.ts.map
    "sourceMap": true,                     // 生成.map文件

    /* 类型检查 */
    "strict": true,                        // 严格模式
    "noImplicitAny": true,                 // 禁止隐式any
    "strictNullChecks": true,              // 严格空值检查
    "strictFunctionTypes": true,           // 严格函数类型
    "noUnusedLocals": true,                // 未使用的局部变量
    "noUnusedParameters": true,            // 未使用的参数
    "noImplicitReturns": true,             // 隐式返回

    /* 互操作性 */
    "esModuleInterop": true,               // ES模块互操作
    "allowSyntheticDefaultImports": true,  // 允许合成默认导入
    "forceConsistentCasingInFileNames": true, // 强制文件名大小写一致

    /* 其他 */
    "skipLibCheck": true,                  // 跳过库文件检查
    "allowJs": true,                       // 允许JS文件
    "checkJs": false                       // 检查JS文件
  }
}

项目引用

使用项目引用管理大型项目:

// tsconfig.base.json
{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true
  }
}

// packages/core/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist"
  },
  "include": ["src"]
}

// packages/app/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist"
  },
  "references": [
    { "path": "../core" }
  ],
  "include": ["src"]
}

ESLint配置

// .eslintrc.js
module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended'
  ],
  plugins: ['@typescript-eslint'],
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    project: './tsconfig.json'
  },
  rules: {
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-unused-vars': ['error', {
      argsIgnorePattern: '^_'
    }]
  }
};

Prettier配置

// .prettierrc
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "arrowParens": "avoid"
}

构建工具集成

Webpack配置

// webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/index.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

Vite配置

// vite.config.ts
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  build: {
    target: 'es2020',
    outDir: 'dist',
    sourcemap: true
  }
});

测试配置

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['/src'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
  transform: {
    '^.+\\.ts$': 'ts-jest'
  },
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.d.ts'
  ],
  moduleNameMapper: {
    '^@/(.*)$': '/src/$1'
  }
};

package.json脚本

{
  "name": "my-typescript-project",
  "version": "1.0.0",
  "scripts": {
    "build": "tsc",
    "build:watch": "tsc --watch",
    "dev": "ts-node src/index.ts",
    "start": "node dist/index.js",
    "lint": "eslint src --ext .ts",
    "lint:fix": "eslint src --ext .ts --fix",
    "format": "prettier --write \"src/**/*.ts\"",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "clean": "rm -rf dist"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "eslint": "^8.0.0",
    "jest": "^29.0.0",
    "prettier": "^3.0.0",
    "ts-jest": "^29.0.0",
    "ts-node": "^10.0.0",
    "typescript": "^5.0.0"
  }
}

Git Hooks配置

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.ts": [
      "eslint --fix",
      "prettier --write",
      "git add"
    ]
  }
}

CI/CD配置

// .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '18'

    - name: Install dependencies
      run: npm ci

    - name: Lint
      run: npm run lint

    - name: Test
      run: npm run test:coverage

    - name: Build
      run: npm run build

Monorepo配置

// lerna.json
{
  "version": "independent",
  "npmClient": "npm",
  "packages": [
    "packages/*"
  ],
  "command": {
    "publish": {
      "ignoreChanges": ["*.md"]
    }
  }
}

// package.json
{
  "workspaces": [
    "packages/*"
  ]
}
工程化最佳实践:
练习:
  1. 创建一个完整的tsconfig.json配置文件
  2. 配置ESLint和Prettier
  3. 设置路径映射和别名
  4. 配置构建脚本和测试环境