在将 Tailwind CSS 项目部署到生产环境时,需要做好各项配置和优化工作。本节将详细介绍如何配置和优化部署环境。

环境配置

Docker 配置

  1. # Dockerfile
  2. # 构建阶段
  3. FROM node:16-alpine as builder
  4. WORKDIR /app
  5. COPY package*.json ./
  6. RUN npm ci
  7. COPY . .
  8. RUN npm run build
  9. # 生产阶段
  10. FROM nginx:alpine
  11. # 复制构建产物
  12. COPY --from=builder /app/dist /usr/share/nginx/html
  13. # 复制 Nginx 配置
  14. COPY nginx.conf /etc/nginx/conf.d/default.conf
  15. EXPOSE 80
  16. CMD ["nginx", "-g", "daemon off;"]

Nginx 配置

  1. # nginx.conf
  2. server {
  3. listen 80;
  4. server_name localhost;
  5. root /usr/share/nginx/html;
  6. index index.html;
  7. # Gzip 压缩
  8. gzip on;
  9. gzip_vary on;
  10. gzip_proxied any;
  11. gzip_comp_level 6;
  12. gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
  13. # 缓存配置
  14. location ~* \.(?:css|js)$ {
  15. expires 1y;
  16. access_log off;
  17. add_header Cache-Control "public";
  18. }
  19. location / {
  20. try_files $uri $uri/ /index.html;
  21. }
  22. }

构建配置

生产环境配置

  1. // tailwind.config.js
  2. module.exports = {
  3. mode: 'jit',
  4. purge: {
  5. enabled: process.env.NODE_ENV === 'production',
  6. content: [
  7. './src/**/*.{js,jsx,ts,tsx}',
  8. './public/index.html'
  9. ],
  10. options: {
  11. safelist: [
  12. /^bg-/,
  13. /^text-/,
  14. 'prose',
  15. 'prose-lg'
  16. ]
  17. }
  18. },
  19. theme: {
  20. extend: {
  21. // 生产环境特定配置
  22. }
  23. }
  24. }

构建脚本

  1. // scripts/build.js
  2. const webpack = require('webpack');
  3. const TerserPlugin = require('terser-webpack-plugin');
  4. const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
  5. module.exports = {
  6. mode: 'production',
  7. optimization: {
  8. minimizer: [
  9. new TerserPlugin({
  10. terserOptions: {
  11. compress: {
  12. drop_console: true,
  13. },
  14. },
  15. }),
  16. new CssMinimizerPlugin({
  17. minimizerOptions: {
  18. preset: [
  19. 'default',
  20. {
  21. discardComments: { removeAll: true },
  22. },
  23. ],
  24. },
  25. }),
  26. ],
  27. },
  28. plugins: [
  29. new webpack.DefinePlugin({
  30. 'process.env.NODE_ENV': JSON.stringify('production'),
  31. }),
  32. ],
  33. };

CI/CD 配置

GitHub Actions

  1. # .github/workflows/deploy.yml
  2. name: Deploy
  3. on:
  4. push:
  5. branches: [ main ]
  6. jobs:
  7. deploy:
  8. runs-on: ubuntu-latest
  9. steps:
  10. - uses: actions/checkout@v2
  11. - name: Setup Node.js
  12. uses: actions/setup-node@v2
  13. with:
  14. node-version: '16'
  15. cache: 'npm'
  16. - name: Install dependencies
  17. run: npm ci
  18. - name: Build
  19. run: npm run build
  20. env:
  21. NODE_ENV: production
  22. - name: Deploy to server
  23. uses: appleboy/scp-action@master
  24. with:
  25. host: ${{ secrets.HOST }}
  26. username: ${{ secrets.USERNAME }}
  27. key: ${{ secrets.SSH_KEY }}
  28. source: "dist/"
  29. target: "/var/www/html"

部署脚本

  1. #!/bin/bash
  2. # deploy.sh
  3. # 环境变量
  4. ENV=$1
  5. CONFIG_FILE="config.$ENV.json"
  6. # 验证参数
  7. if [ -z "$ENV" ]; then
  8. echo "Please specify environment (dev/staging/prod)"
  9. exit 1
  10. fi
  11. # 构建项目
  12. echo "Building for $ENV environment..."
  13. npm run build:$ENV
  14. # 部署到服务器
  15. echo "Deploying to $ENV server..."
  16. rsync -avz --delete dist/ user@server:/path/to/$ENV/
  17. # 清理缓存
  18. echo "Clearing cache..."
  19. curl -X POST https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache \
  20. -H "Authorization: Bearer $CF_TOKEN" \
  21. -H "Content-Type: application/json" \
  22. --data '{"purge_everything":true}'
  23. echo "Deployment completed!"

性能优化

静态资源优化

  1. // webpack.prod.js
  2. const CompressionPlugin = require('compression-webpack-plugin');
  3. const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
  4. module.exports = {
  5. plugins: [
  6. new CompressionPlugin({
  7. test: /\.(js|css|html|svg)$/,
  8. algorithm: 'gzip',
  9. }),
  10. new ImageMinimizerPlugin({
  11. minimizer: {
  12. implementation: ImageMinimizerPlugin.imageminMinify,
  13. options: {
  14. plugins: [
  15. ['mozjpeg', { quality: 80 }],
  16. ['pngquant', { quality: [0.6, 0.8] }],
  17. ['svgo', {
  18. plugins: [
  19. { removeViewBox: false },
  20. { removeEmptyAttrs: false }
  21. ]
  22. }]
  23. ]
  24. }
  25. }
  26. })
  27. ]
  28. };

缓存策略

  1. // next.config.js
  2. module.exports = {
  3. generateBuildId: async () => {
  4. // 使用 Git commit hash 作为构建 ID
  5. return require('child_process')
  6. .execSync('git rev-parse HEAD')
  7. .toString().trim()
  8. },
  9. // 静态资源缓存配置
  10. async headers() {
  11. return [
  12. {
  13. source: '/_next/static/:path*',
  14. headers: [
  15. {
  16. key: 'Cache-Control',
  17. value: 'public, max-age=31536000, immutable'
  18. }
  19. ]
  20. }
  21. ]
  22. }
  23. }

监控配置

性能监控

  1. // utils/monitoring.ts
  2. export const setupPerformanceMonitoring = () => {
  3. // Web Vitals 监控
  4. import('web-vitals').then(({ getCLS, getFID, getLCP }) => {
  5. getCLS(console.log);
  6. getFID(console.log);
  7. getLCP(console.log);
  8. });
  9. // 错误监控
  10. window.addEventListener('error', (event) => {
  11. console.error('Global error:', event.error);
  12. // 发送到监控服务
  13. });
  14. // 性能标记
  15. performance.mark('app-start');
  16. return () => {
  17. performance.measure('app-load', 'app-start');
  18. const measurements = performance.getEntriesByType('measure');
  19. console.log('Performance measurements:', measurements);
  20. };
  21. };

日志配置

  1. // utils/logger.ts
  2. type LogLevel = 'info' | 'warn' | 'error';
  3. class Logger {
  4. private env: string;
  5. constructor() {
  6. this.env = process.env.NODE_ENV || 'development';
  7. }
  8. log(level: LogLevel, message: string, data?: any) {
  9. const timestamp = new Date().toISOString();
  10. const logData = {
  11. timestamp,
  12. level,
  13. message,
  14. data,
  15. env: this.env
  16. };
  17. if (this.env === 'production') {
  18. // 发送到日志服务
  19. fetch('/api/logs', {
  20. method: 'POST',
  21. body: JSON.stringify(logData)
  22. });
  23. } else {
  24. console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`, data);
  25. }
  26. }
  27. }
  28. export const logger = new Logger();

安全配置

内容安全策略

  1. // next.config.js
  2. const securityHeaders = [
  3. {
  4. key: 'Content-Security-Policy',
  5. value: `
  6. default-src 'self';
  7. style-src 'self' 'unsafe-inline';
  8. script-src 'self' 'unsafe-eval';
  9. img-src 'self' data: https:;
  10. font-src 'self';
  11. `.replace(/\s{2,}/g, ' ').trim()
  12. },
  13. {
  14. key: 'X-XSS-Protection',
  15. value: '1; mode=block'
  16. },
  17. {
  18. key: 'X-Frame-Options',
  19. value: 'SAMEORIGIN'
  20. },
  21. {
  22. key: 'X-Content-Type-Options',
  23. value: 'nosniff'
  24. }
  25. ];
  26. module.exports = {
  27. async headers() {
  28. return [
  29. {
  30. source: '/:path*',
  31. headers: securityHeaders,
  32. },
  33. ]
  34. }
  35. }

最佳实践

  1. 部署准备

    • 环境配置完整
    • 构建流程优化
    • 部署脚本准备
  2. 性能优化

    • 资源压缩
    • 缓存策略
    • 监控配置
  3. 安全考虑

    • 安全头部配置
    • 错误处理
    • 日志记录
  4. 维护策略

    • 自动化部署
    • 监控告警
    • 回滚机制