Skip to content

TypeScript 工程化模板 🚀

简介

本指南提供了一个完整的 TypeScript 项目构建模板,包含开发、测试、构建和部署的完整工作流程。

  • 开发环境配置 💻
  • 构建流程管理 ⚙️
  • 代码质量控制 🛡️
  • 自动化部署 🚀
  • 性能优化 ⚡

项目初始化

基础配置

bash
# 创建项目目录
mkdir my-ts-project
cd my-ts-project

# 初始化 package.json
npm init -y

# 安装核心依赖
npm install typescript @types/node ts-node nodemon tsconfig-paths -D  # ts,node,ts-node,nodemon,tsconfig-paths
json
{
  "name": "my-ts-project",
  "version": "1.0.0",
  "scripts": {
    // "dev": "ts-node -r tsconfig-paths/register src/index.ts",
    "dev:watch": "nodemon --watch src -e ts,tsx --exec \"ts-node -r tsconfig-paths/register\" src/main.ts",
    "build": "tsc",
    "start": "node dist/main.js",
    "lint": "eslint src --ext .ts",
    "format": "prettier --write \"src/**/*.ts\"",
    "test": "jest",
    "clean": "rimraf dist"
  }
}
json
{
  // 编译器选项 - 配置 TypeScript 编译器的行为
  "compilerOptions": {
    // JavaScript 语言级别和环境配置
    "target": "ES5",          // 编译后的 JavaScript 版本,ES2020支持最新的语言特性
    "module": "CommonJS",        // 使用 CommonJS 模块系统,适用于 Node.js 环境
    
    // 输出文件配置
    "outDir": "./dist",          // 编译后的文件输出目录
    "rootDir": "./src",          // TypeScript 源文件的根目录
    
    // 类型检查和严格模式
    "strict": true,              // 启用所有严格的类型检查选项
                                // 包括 strictNullChecks, strictFunctionTypes 等
    
    // 模块解析配置
    "esModuleInterop": true,     // 允许使用 import 导入 CommonJS 模块
                                // 使得模块导入更符合 ES6 规范
    "skipLibCheck": true,        // 跳过对声明文件(*.d.ts)的类型检查
                                // 可以提升编译性能
    "forceConsistentCasingInFileNames": true,  // 强制文件名大小写一致
                                              // 避免在不同操作系统间的问题
    "moduleResolution": "node",   // 使用 Node.js 风格的模块解析策略
                                // 更好地支持第三方包的导入
    
    // 额外功能支持
    "resolveJsonModule": true,    // 允许导入 JSON 文件作为模块
                                // 可以直接 import 配置文件
    "declaration": true,          // 为每个 TypeScript 文件生成对应的 .d.ts 文件
                                // 便于其他项目引用类型定义
    "sourceMap": true,           // 生成源码映射文件 (.map)
                                // 便于在浏览器中调试 TypeScript 代码
    
    // 路径解析配置
    "baseUrl": ".",             // 非相对模块导入的基准目录
    "paths": {                  // 路径别名配置,简化模块导入
      "@/*": ["src/*"]         // 例如:import '@/utils' 等同于 import 'src/utils'
    }
  },

  // 项目文件配置
  "include": [
    "src/**/*"                  // 包含 src 目录及其子目录下的所有 TypeScript 文件
  ],
  
  // 排除项配置
  "exclude": [
    "node_modules",             // 排除 node_modules 目录,避免编译第三方包
    "dist",                     // 排除输出目录,避免重复编译
    "**/*.test.ts"             // 排除测试文件,通常由测试工具单独处理
  ]
}

代码质量工具

json
{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/explicit-function-return-type": "warn",
    "@typescript-eslint/no-explicit-any": "warn"
  }
}
json
{
  "semi": true,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2
}
json
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/src'],
  testMatch: ['**/*.test.ts'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  }
};

项目结构

标准项目结构

my-ts-project/
├── src/                    # 源代码目录
│   ├── config/            # 配置文件
│   ├── controllers/       # 控制器
│   ├── models/           # 数据模型
│   ├── services/         # 业务逻辑
│   ├── utils/            # 工具函数
│   ├── types/            # 类型定义
│   └── index.ts          # 入口文件
├── tests/                 # 测试文件
├── dist/                  # 编译输出
├── node_modules/         # 依赖包
├── package.json          # 项目配置
├── tsconfig.json         # TS配置
├── .eslintrc            # ESLint配置
├── .prettierrc          # Prettier配置
├── .gitignore           # Git忽略文件
└── README.md            # 项目说明

开发脚本

基本命令

常用命令

bash
# 开发环境运行
npm run dev

# 构建生产版本
npm run build

# 运行生产版本
npm start

# 代码检查
npm run lint

# 代码格式化
npm run format

# 运行测试
npm run test

# 清理构建文件
npm run clean

开发工具链

依赖安装
bash
# 开发依赖
npm install -D typescript @types/node ts-node nodemon  # ts,node,ts-node,nodemon

# 代码检查  
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin  # eslint,typescript-eslint
npm install -D prettier eslint-config-prettier eslint-plugin-prettier  # prettier

# 测试
npm install -D jest @types/jest ts-jest  # jest

# 清理
npm install -D rimraf  # rimraf

# 可选依赖
npm install -D husky lint-staged          # Git hooks
npm install -D @commitlint/cli @commitlint/config-conventional  # Commit 规范
npm install -D cross-env                  # 跨平台环境变量

环境配置

环境变量

bash
NODE_ENV=development
PORT=3000
API_URL=http://localhost:8080
bash
NODE_ENV=production
PORT=8080
API_URL=https://api.example.com
typescript
import dotenv from 'dotenv';
import path from 'path';

const envFile = process.env.NODE_ENV === 'production' 
  ? '.env.production' 
  : '.env.development';

dotenv.config({ path: path.resolve(process.cwd(), envFile) });

export const config = {
  nodeEnv: process.env.NODE_ENV,
  port: process.env.PORT,
  apiUrl: process.env.API_URL,
};

构建配置

生产构建

构建脚本
json
{
  "scripts": {
    "build:clean": "rimraf dist",
    "build:tsc": "tsc",
    "build:assets": "copyfiles -u 1 src/**/*.{json,graphql} dist",
    "build": "npm run build:clean && npm run build:tsc && npm run build:assets"
  }
}

性能优化

优化建议

  1. 使用 tsconfig.jsonpaths 实现路径别名
  2. 启用增量编译 "incremental": true
  3. 使用 ts-nodeswc 编译器提升开发环境性能
  4. 合理配置 includeexclude
  5. 使用 Project References 进行项目拆分

常见问题

常见问题解决

  1. 路径别名不生效

    • 检查 tsconfig.jsonpaths 配置
    • 确保构建工具支持路径别名
  2. 构建性能问题

    • 使用 tsc --diagnostics 分析编译性能
    • 检查 includeexclude 配置
  3. 依赖类型问题

    • 安装对应的 @types
    • 创建自定义的类型声明文件

路径别名问题解决

当你遇到类似这样的错误:

bash
Error: Cannot find module '@/utils/random'
Require stack:
- G:\Code\Project\study\rollup\src\main.ts

这是因为 TypeScript 的路径别名配置(tsconfig.json 中的 paths)只对 TypeScript 的类型检查生效,运行时的模块解析需要额外配置。解决方案如下:

  1. 开发环境(ts-node)
bash
# 安装必要的依赖
npm install -D tsconfig-paths
json
{
  "scripts": {
    // 基础用法
    "dev": "ts-node -r tsconfig-paths/register src/main.ts",
    
    // 如果使用 nodemon(支持热重载)
    "dev": "nodemon --watch src -e ts,tsx --exec \"ts-node -r tsconfig-paths/register\" src/main.ts"
  }
}
  1. 生产环境(使用 Rollup)
bash
# 安装必要的依赖
npm install -D @rollup/plugin-alias
javascript
import alias from '@rollup/plugin-alias';
import path from 'path';

export default {
  // ... 其他配置
  plugins: [
    alias({
      entries: [
        { 
          find: '@', 
          replacement: path.resolve(__dirname, 'src') 
        }
      ]
    })
    // ... 其他插件
  ]
}
  1. 生产环境(使用 Webpack)
javascript
const path = require('path');

module.exports = {
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
}
  1. 不使用打包工具时
bash
npm install module-alias
json
{
  "_moduleAliases": {
    "@": "dist"  // 注意这里指向编译后的目录
  }
}
typescript
import 'module-alias/register';  // 在入口文件最开始引入

最佳实践

  1. 确保配置的一致性:

    • tsconfig.json 中的 paths
    • 构建工具(Rollup/Webpack)中的 alias 配置
    • 开发环境的 tsconfig-paths 配置
  2. 检查项目结构:

    • 确保源文件在 src 目录下
    • 确保引用路径正确(区分大小写)
    • 检查文件扩展名(.ts, .js, .json 等)
  3. IDE 配置:

    • VS Code 需要重新加载窗口使路径别名生效
    • 确保 TypeScript 插件已更新到最新版本
  4. 常见陷阱:

    • 路径大小写不匹配
    • 文件扩展名问题
    • 编译后的路径映射问题

注意事项

  1. 开发环境和生产环境的路径解析机制是不同的:

    • 开发环境依赖 ts-nodetsconfig-paths
    • 生产环境依赖构建工具的别名配置
  2. 使用打包工具时:

    • Rollup 需要 @rollup/plugin-alias
    • Webpack 内置了 alias 支持
    • 确保别名配置与 tsconfig.json 保持一致
  3. 调试技巧:

    • 使用 console.log(require.resolve('@/utils/random')) 查看模块解析路径
    • 检查编译后的代码中路径是否正确
    • 使用 --verbose 参数查看详细的模块解析过程

部署指南

部署检查清单

  1. 环境变量配置
  2. 构建优化
  3. 错误处理
  4. 日志配置
  5. 性能监控
  6. 安全检查
  7. 备份策略

开发工具

  • VS Code + TypeScript 插件
  • Docker Desktop
  • Postman/Insomnia
  • GitKraken/SourceTree
  • PM2 (生产环境进程管理)