前端工程化
目录
构建工具
Webpack
javascript
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
],
optimization: {
splitChunks: {
chunks: 'all'
}
}
};说明:
- Webpack 是模块打包工具
- 支持多种文件类型
- 可以优化资源加载
- 支持代码分割
Vite
javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
},
build: {
outDir: 'dist',
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash', 'axios']
}
}
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
});说明:
- Vite 是新一代构建工具
- 开发环境使用原生 ESM
- 生产环境使用 Rollup
- 支持热更新
Rollup
javascript
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/index.js',
output: [
{
file: 'dist/bundle.js',
format: 'cjs'
},
{
file: 'dist/bundle.esm.js',
format: 'esm'
}
],
plugins: [
resolve(),
commonjs(),
babel({
babelHelpers: 'bundled',
presets: ['@babel/preset-env']
}),
terser()
],
external: ['react', 'react-dom']
};说明:
- Rollup 是模块打包器
- 适合库的开发
- 支持 Tree Shaking
- 可以生成多种格式
包管理
npm
bash
# 初始化项目
npm init
# 安装依赖
npm install react react-dom
# 安装开发依赖
npm install --save-dev webpack webpack-cli
# 运行脚本
npm run dev
# 发布包
npm publish说明:
- npm 是 Node.js 包管理器
- 使用 package.json 管理依赖
- 支持脚本命令
- 可以发布包
yarn
bash
# 初始化项目
yarn init
# 安装依赖
yarn add react react-dom
# 安装开发依赖
yarn add -D webpack webpack-cli
# 运行脚本
yarn dev
# 发布包
yarn publish说明:
- yarn 是 npm 的替代品
- 使用 yarn.lock 锁定版本
- 并行安装依赖
- 更好的缓存机制
pnpm
bash
# 初始化项目
pnpm init
# 安装依赖
pnpm add react react-dom
# 安装开发依赖
pnpm add -D webpack webpack-cli
# 运行脚本
pnpm dev
# 发布包
pnpm publish说明:
- pnpm 使用硬链接
- 节省磁盘空间
- 更快的安装速度
- 更严格的依赖管理
代码规范
ESLint
javascript
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 12,
sourceType: 'module'
},
plugins: ['react', '@typescript-eslint'],
rules: {
'no-console': 'warn',
'react/prop-types': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off'
},
settings: {
react: {
version: 'detect'
}
}
};说明:
- ESLint 是代码检查工具
- 可以自定义规则
- 支持多种框架
- 可以自动修复
Prettier
javascript
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80,
"bracketSpacing": true,
"arrowParens": "avoid"
}说明:
- Prettier 是代码格式化工具
- 可以统一代码风格
- 支持多种语言
- 可以集成到编辑器
TypeScript
typescript
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
// 类型定义
interface User {
id: number;
name: string;
email: string;
age?: number;
}
// 使用类型
const user: User = {
id: 1,
name: 'John',
email: '[email protected]'
};说明:
- TypeScript 是 JavaScript 的超集
- 添加静态类型
- 提供更好的开发体验
- 减少运行时错误
测试
单元测试
javascript
// 使用 Jest
describe('Calculator', () => {
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
test('subtracts 5 - 3 to equal 2', () => {
expect(subtract(5, 3)).toBe(2);
});
});
// 使用 React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
test('renders button and handles click', () => {
render(<Button onClick={() => console.log('clicked')}>Click me</Button>);
const button = screen.getByText('Click me');
fireEvent.click(button);
expect(console.log).toHaveBeenCalledWith('clicked');
});说明:
- 单元测试测试独立功能
- 使用 Jest 作为测试框架
- 使用 React Testing Library 测试组件
- 可以模拟用户交互
集成测试
javascript
// 使用 Cypress
describe('Login Flow', () => {
beforeEach(() => {
cy.visit('/login');
});
it('should login successfully', () => {
cy.get('[data-testid=username]').type('testuser');
cy.get('[data-testid=password]').type('password123');
cy.get('[data-testid=submit]').click();
cy.url().should('include', '/dashboard');
});
it('should show error for invalid credentials', () => {
cy.get('[data-testid=username]').type('wronguser');
cy.get('[data-testid=password]').type('wrongpass');
cy.get('[data-testid=submit]').click();
cy.get('[data-testid=error]').should('be.visible');
});
});说明:
- 集成测试测试多个组件
- 使用 Cypress 进行端到端测试
- 可以测试用户流程
- 可以模拟真实环境
端到端测试
javascript
// 使用 Playwright
import { test, expect } from '@playwright/test';
test('complete user journey', async ({ page }) => {
// 登录
await page.goto('/login');
await page.fill('[data-testid=username]', 'testuser');
await page.fill('[data-testid=password]', 'password123');
await page.click('[data-testid=submit]');
// 验证登录成功
await expect(page).toHaveURL('/dashboard');
// 创建新项目
await page.click('[data-testid=new-project]');
await page.fill('[data-testid=project-name]', 'Test Project');
await page.click('[data-testid=create]');
// 验证项目创建成功
await expect(page.locator('[data-testid=project-list]')).toContainText('Test Project');
});说明:
- 端到端测试测试完整流程
- 使用 Playwright 进行测试
- 可以测试跨浏览器兼容性
- 可以测试性能
部署
CI/CD
yaml
# GitHub Actions
name: CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm ci
- run: npm run build
- run: npm test
- name: Deploy
if: github.ref == 'refs/heads/main'
run: |
# 部署步骤说明:
- CI/CD 自动化构建和部署
- 使用 GitHub Actions
- 可以自动运行测试
- 可以自动部署
Docker
dockerfile
# Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]说明:
- Docker 用于容器化应用
- 可以确保环境一致性
- 可以快速部署
- 可以水平扩展
Nginx
nginx
# nginx.conf
server {
listen 80;
server_name example.com;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static {
expires 1y;
add_header Cache-Control "public, no-transform";
}
}说明:
- Nginx 是 Web 服务器
- 可以处理静态文件
- 可以反向代理
- 可以配置缓存
最佳实践
1. 项目结构
- 使用模块化组织代码
- 遵循约定优于配置
- 保持目录结构清晰
- 使用有意义的命名
2. 开发流程
- 使用 Git Flow
- 进行代码审查
- 编写测试用例
- 持续集成和部署
3. 性能优化
- 使用代码分割
- 优化资源加载
- 使用缓存策略
- 监控性能指标
4. 安全
- 使用 HTTPS
- 防止 XSS 攻击
- 防止 CSRF 攻击
- 定期更新依赖
学习资源
在线教程
视频课程
- 慕课网
- 极客时间
- B站技术区
- YouTube 技术频道