故障排除指南
本指南帮助您诊断和解决在使用 Trae 开发平台时可能遇到的常见问题。
概述
故障排除是开发过程中的重要技能。本指南按问题类型分类,提供系统性的解决方案和预防措施,帮助您快速定位和解决问题。
安装和设置问题
Node.js 版本兼容性
问题:项目无法启动,提示 Node.js 版本不兼容
bash
Error: The engine "node" is incompatible with this module.解决方案:
- 检查当前 Node.js 版本:
bash
node --version- 检查项目要求的版本:
json
// package.json
{
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
}
}- 使用 nvm 切换版本:
bash
# 安装指定版本
nvm install 18.17.0
nvm use 18.17.0
# 设置默认版本
nvm alias default 18.17.0- 或使用 .nvmrc 文件:
bash
# .nvmrc
18.17.0bash
nvm use依赖安装失败
问题:npm install 或 yarn install 失败
常见错误和解决方案:
- 网络问题:
bash
# 使用国内镜像
npm config set registry https://registry.npmmirror.com/
# 或使用 yarn
yarn config set registry https://registry.npmmirror.com/- 权限问题:
bash
# 清理缓存
npm cache clean --force
# 删除 node_modules 和 package-lock.json
rm -rf node_modules package-lock.json
npm install- 依赖冲突:
bash
# 查看依赖树
npm ls
# 安装特定版本
npm install package@version
# 使用 --legacy-peer-deps
npm install --legacy-peer-deps端口占用问题
问题:开发服务器无法启动,端口被占用
bash
Error: listen EADDRINUSE: address already in use :::3000解决方案:
- 查找占用端口的进程:
bash
# macOS/Linux
lsof -ti:3000
# Windows
netstat -ano | findstr :3000- 终止进程:
bash
# macOS/Linux
kill -9 $(lsof -ti:3000)
# Windows
taskkill /PID <PID> /F- 使用不同端口:
bash
# 临时使用
PORT=3001 npm start
# 或在 .env 文件中设置
PORT=3001构建和编译问题
TypeScript 编译错误
问题:TypeScript 类型检查失败
常见错误和解决方案:
- 类型定义缺失:
bash
# 安装类型定义
npm install --save-dev @types/node @types/react @types/react-dom- 严格模式错误:
json
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": false,
"strictNullChecks": false
}
}- 路径映射问题:
json
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"]
}
}
}Webpack 构建错误
问题:Webpack 构建失败或警告
解决方案:
- 内存不足:
bash
# 增加 Node.js 内存限制
node --max-old-space-size=4096 node_modules/.bin/webpack
# 或在 package.json 中设置
{
"scripts": {
"build": "node --max-old-space-size=4096 node_modules/.bin/react-scripts build"
}
}- 模块解析错误:
javascript
// webpack.config.js
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components')
},
fallback: {
"path": require.resolve("path-browserify"),
"os": require.resolve("os-browserify/browser"),
"crypto": require.resolve("crypto-browserify")
}
}
};- CSS 处理错误:
javascript
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
},
'postcss-loader'
]
}
]
}
};环境变量问题
问题:环境变量未正确加载
解决方案:
- 检查文件命名:
bash
# 正确的文件名
.env # 默认环境
.env.local # 本地覆盖
.env.development # 开发环境
.env.production # 生产环境- 变量命名规范:
bash
# React 应用中必须以 REACT_APP_ 开头
REACT_APP_API_URL=http://localhost:3001
REACT_APP_APP_NAME=My App
# Node.js 应用中可以任意命名
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=your-secret-key- 加载顺序检查:
javascript
// 在应用入口检查环境变量
console.log('Environment variables:', {
NODE_ENV: process.env.NODE_ENV,
REACT_APP_API_URL: process.env.REACT_APP_API_URL,
// 其他变量...
});运行时错误
React 组件错误
问题:组件渲染错误或无限循环
常见错误和解决方案:
- 无限渲染循环:
javascript
// 错误示例
function Component() {
const [count, setCount] = useState(0);
// 错误:每次渲染都会调用
setCount(count + 1);
return <div>{count}</div>;
}
// 正确示例
function Component() {
const [count, setCount] = useState(0);
// 正确:在事件处理器中调用
const handleClick = () => {
setCount(count + 1);
};
return <div onClick={handleClick}>{count}</div>;
}- 依赖数组问题:
javascript
// 错误示例
useEffect(() => {
fetchData();
}, []); // 缺少依赖
// 正确示例
useEffect(() => {
fetchData();
}, [userId, filters]); // 包含所有依赖
// 或使用 useCallback
const fetchData = useCallback(() => {
// 获取数据逻辑
}, [userId, filters]);
useEffect(() => {
fetchData();
}, [fetchData]);- 状态更新错误:
javascript
// 错误示例
const [items, setItems] = useState([]);
const addItem = (newItem) => {
items.push(newItem); // 直接修改状态
setItems(items);
};
// 正确示例
const addItem = (newItem) => {
setItems(prevItems => [...prevItems, newItem]);
};网络请求错误
问题:API 请求失败或超时
解决方案:
- CORS 错误:
javascript
// 开发环境代理配置
// package.json
{
"proxy": "http://localhost:3001"
}
// 或使用 setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true
})
);
};- 请求超时处理:
javascript
// 使用 axios 设置超时
import axios from 'axios';
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
timeout: 10000, // 10秒超时
headers: {
'Content-Type': 'application/json'
}
});
// 请求拦截器
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.code === 'ECONNABORTED') {
console.error('Request timeout');
} else if (error.response?.status === 401) {
// 处理认证错误
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);- 错误重试机制:
javascript
// 自动重试函数
const retryRequest = async (fn, retries = 3, delay = 1000) => {
try {
return await fn();
} catch (error) {
if (retries > 0 && error.response?.status >= 500) {
await new Promise(resolve => setTimeout(resolve, delay));
return retryRequest(fn, retries - 1, delay * 2);
}
throw error;
}
};
// 使用示例
const fetchUserData = async (userId) => {
return retryRequest(() => api.get(`/users/${userId}`));
};内存泄漏问题
问题:应用内存使用持续增长
解决方案:
- 清理事件监听器:
javascript
useEffect(() => {
const handleResize = () => {
// 处理窗口大小变化
};
window.addEventListener('resize', handleResize);
// 清理函数
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);- 清理定时器:
javascript
useEffect(() => {
const timer = setInterval(() => {
// 定时任务
}, 1000);
return () => {
clearInterval(timer);
};
}, []);- 取消未完成的请求:
javascript
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await fetch('/api/data', {
signal: controller.signal
});
const data = await response.json();
setData(data);
} catch (error) {
if (error.name !== 'AbortError') {
console.error('Fetch error:', error);
}
}
};
fetchData();
return () => {
controller.abort();
};
}, []);性能问题
渲染性能优化
问题:组件渲染缓慢或卡顿
解决方案:
- 使用 React.memo:
javascript
// 优化函数组件
const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
return (
<div>
{data.map(item => (
<Item key={item.id} item={item} onUpdate={onUpdate} />
))}
</div>
);
}, (prevProps, nextProps) => {
// 自定义比较函数
return prevProps.data.length === nextProps.data.length &&
prevProps.onUpdate === nextProps.onUpdate;
});- 使用 useMemo 和 useCallback:
javascript
function Component({ items, filter }) {
// 缓存计算结果
const filteredItems = useMemo(() => {
return items.filter(item => item.category === filter);
}, [items, filter]);
// 缓存回调函数
const handleItemClick = useCallback((itemId) => {
// 处理点击事件
}, []);
return (
<div>
{filteredItems.map(item => (
<Item
key={item.id}
item={item}
onClick={handleItemClick}
/>
))}
</div>
);
}- 虚拟化长列表:
javascript
import { FixedSizeList as List } from 'react-window';
function VirtualizedList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
<Item item={items[index]} />
</div>
);
return (
<List
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{Row}
</List>
);
}包大小优化
问题:构建产物过大,加载缓慢
解决方案:
- 分析包大小:
bash
# 安装分析工具
npm install --save-dev webpack-bundle-analyzer
# 分析构建产物
npx webpack-bundle-analyzer build/static/js/*.js- 代码分割:
javascript
// 路由级别的代码分割
import { lazy, Suspense } from 'react';
const HomePage = lazy(() => import('./pages/HomePage'));
const AboutPage = lazy(() => import('./pages/AboutPage'));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</Suspense>
</Router>
);
}- 按需导入:
javascript
// 错误:导入整个库
import _ from 'lodash';
// 正确:按需导入
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
// 或使用 babel-plugin-import
// .babelrc
{
"plugins": [
["import", {
"libraryName": "lodash",
"libraryDirectory": "",
"camel2DashComponentName": false
}, "lodash"]
]
}调试技巧
React DevTools
使用 React DevTools 调试组件:
组件检查:
- 查看组件树结构
- 检查 props 和 state
- 追踪状态变化
性能分析:
- 使用 Profiler 标签
- 记录组件渲染时间
- 识别性能瓶颈
Hook 调试:
javascript
// 使用 useDebugValue
function useCustomHook(value) {
const [state, setState] = useState(value);
// 在 DevTools 中显示调试信息
useDebugValue(state, state => `Custom Hook: ${state}`);
return [state, setState];
}浏览器调试
使用浏览器开发者工具:
- 断点调试:
javascript
// 在代码中设置断点
function handleSubmit(data) {
debugger; // 浏览器会在此处暂停
// 处理表单提交
processFormData(data);
}- 条件断点:
javascript
// 在浏览器中设置条件断点
function processItems(items) {
items.forEach((item, index) => {
// 在 DevTools 中设置条件:index === 5
processItem(item);
});
}- 网络调试:
- 检查 Network 标签
- 查看请求和响应
- 模拟网络条件
日志调试
有效的日志记录:
javascript
// 结构化日志
const logger = {
info: (message, data) => {
console.log(`[INFO] ${message}`, data);
},
warn: (message, data) => {
console.warn(`[WARN] ${message}`, data);
},
error: (message, error) => {
console.error(`[ERROR] ${message}`, error);
},
debug: (message, data) => {
if (process.env.NODE_ENV === 'development') {
console.debug(`[DEBUG] ${message}`, data);
}
}
};
// 使用示例
logger.info('User login attempt', { userId, timestamp: Date.now() });
logger.error('API request failed', error);常见错误代码
HTTP 状态码
| 状态码 | 含义 | 常见原因 | 解决方案 |
|---|---|---|---|
| 400 | Bad Request | 请求参数错误 | 检查请求参数格式和类型 |
| 401 | Unauthorized | 认证失败 | 检查 token 是否有效 |
| 403 | Forbidden | 权限不足 | 检查用户权限设置 |
| 404 | Not Found | 资源不存在 | 检查 URL 路径和资源 |
| 429 | Too Many Requests | 请求频率过高 | 实现请求限流和重试 |
| 500 | Internal Server Error | 服务器内部错误 | 检查服务器日志 |
JavaScript 错误
| 错误类型 | 常见原因 | 解决方案 |
|---|---|---|
| TypeError | 访问 undefined/null 的属性 | 使用可选链操作符 ?. |
| ReferenceError | 变量未定义 | 检查变量声明和作用域 |
| SyntaxError | 语法错误 | 检查代码语法 |
| RangeError | 数值超出范围 | 检查数组索引和数值范围 |
预防措施
代码质量
- 使用 ESLint 和 Prettier:
json
// .eslintrc.js
module.exports = {
extends: [
'react-app',
'react-app/jest',
'@typescript-eslint/recommended'
],
rules: {
'no-console': 'warn',
'no-debugger': 'error',
'prefer-const': 'error',
'no-unused-vars': 'error'
}
};- 类型检查:
typescript
// 使用 TypeScript 进行类型检查
interface User {
id: number;
name: string;
email: string;
}
function updateUser(user: User): Promise<User> {
return api.put(`/users/${user.id}`, user);
}- 单元测试:
javascript
// 编写全面的测试
describe('UserService', () => {
it('should handle API errors gracefully', async () => {
const mockError = new Error('Network error');
jest.spyOn(api, 'get').mockRejectedValue(mockError);
await expect(userService.getUser(1)).rejects.toThrow('Network error');
});
});监控和告警
- 错误监控:
javascript
// 使用 Sentry 进行错误监控
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: process.env.REACT_APP_SENTRY_DSN,
environment: process.env.NODE_ENV,
beforeSend(event) {
// 过滤敏感信息
if (event.exception) {
const error = event.exception.values[0];
if (error.value?.includes('password')) {
return null;
}
}
return event;
}
});- 性能监控:
javascript
// 使用 Web Vitals 监控性能
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
// 发送到分析服务
analytics.track('Web Vital', {
name: metric.name,
value: metric.value,
id: metric.id
});
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);通过遵循这些故障排除指南和预防措施,您可以更有效地诊断和解决问题,提高开发效率和应用质量。