文件优化策略

前端项目中常用的文件优化方法

问题

前端项目中有哪些文件优化策略?如何减少文件体积、提升加载速度?

解答

1. 代码压缩

// webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      // JS 压缩
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,  // 移除 console
            drop_debugger: true  // 移除 debugger
          }
        }
      }),
      // CSS 压缩
      new CssMinimizerPlugin()
    ]
  }
};

2. 图片优化

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/i,
        type: 'asset',
        parser: {
          // 小于 8kb 转 base64
          dataUrlCondition: { maxSize: 8 * 1024 }
        }
      }
    ]
  }
};
<!-- 响应式图片 -->
<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="fallback">
</picture>

<!-- 图片懒加载 -->
<img src="placeholder.jpg" data-src="real-image.jpg" loading="lazy">

3. 代码分割

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        // 第三方库单独打包
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10
        },
        // 公共模块
        common: {
          minChunks: 2,
          name: 'common',
          priority: 5
        }
      }
    }
  }
};
// 路由懒加载
const Home = () => import('./views/Home.vue');
const About = () => import('./views/About.vue');

// 动态导入
button.onclick = async () => {
  const { heavyFunction } = await import('./heavy-module.js');
  heavyFunction();
};

4. Tree Shaking

// utils.js - 使用 ES Module 导出
export function used() {
  return 'I am used';
}

export function unused() {
  return 'I will be removed';
}

// main.js - 只导入需要的
import { used } from './utils';  // unused 会被移除
// package.json
{
  "sideEffects": false  // 标记无副作用,允许 tree shaking
}

5. Gzip/Brotli 压缩

// webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  plugins: [
    new CompressionPlugin({
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
      threshold: 10240,  // 大于 10kb 才压缩
      minRatio: 0.8
    })
  ]
};
# nginx 配置
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1024;

6. 缓存策略

// webpack.config.js
module.exports = {
  output: {
    // 内容变化时 hash 才变
    filename: '[name].[contenthash:8].js',
    chunkFilename: '[name].[contenthash:8].chunk.js'
  }
};
# nginx 缓存配置
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

7. 资源预加载

<!-- 预加载关键资源 -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="main.js" as="script">

<!-- 预连接第三方域名 -->
<link rel="preconnect" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://api.example.com">

<!-- 预获取下一页资源 -->
<link rel="prefetch" href="next-page.js">

关键点

  • 代码压缩:使用 Terser 压缩 JS,CssMinimizerPlugin 压缩 CSS
  • 图片优化:选择合适格式(WebP)、压缩、懒加载、小图转 base64
  • 代码分割:splitChunks 分离第三方库,路由懒加载减少首屏体积
  • Tree Shaking:使用 ES Module,配置 sideEffects 移除无用代码
  • 传输压缩:开启 Gzip/Brotli,通常能减少 60%-80% 体积
  • 缓存策略:contenthash 命名 + 长期缓存,避免重复下载