Skip to content

Webpack

文件指纹

文件指纹(File Fingerprint)是指在打包后的文件名中添加一串 hash 值,用于标识文件内容的变化。这对于浏览器缓存优化非常重要,因为当文件内容发生变化时,文件名也会改变,从而强制浏览器重新加载新文件。

文件指纹的类型

  1. Hash:整个项目的 hash 值,项目文件有变化时,所有文件的 hash 值都会改变
  2. Chunkhash:根据不同的入口文件(Entry)进行依赖文件解析,构建对应的 chunk,生成对应的 hash 值
  3. Contenthash:根据文件内容生成 hash 值,文件内容不变,hash 值不变

文件指纹的配置

javascript
// webpack.config.js
module.exports = {
  output: {
    filename: '[name].[chunkhash:8].js', // JS 文件指纹
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css', // CSS 文件指纹
    }),
    new CleanWebpackPlugin(),
  ],
}

图片文件指纹

javascript
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[hash:8].[ext]', // 图片文件指纹
            },
          },
        ],
      },
    ],
  },
}

最佳实践

  1. JS 文件使用 chunkhash

    • 原因:JS 文件通常由 webpack 打包生成,使用 chunkhash 可以确保只有相关文件变化时才会改变 hash 值
  2. CSS 文件使用 contenthash

    • 原因:CSS 文件内容变化时才会改变 hash 值,避免不必要的缓存失效
  3. 图片等静态资源使用 hash

    • 原因:图片等静态资源通常不会频繁变化,使用 hash 可以确保内容变化时更新缓存

实际应用示例

javascript
// webpack.config.js
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  entry: {
    app: './src/index.js',
    vendor: './src/vendor.js',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[chunkhash:8].js',
    chunkFilename: '[name].[chunkhash:8].js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[hash:8].[ext]',
              outputPath: 'images/',
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css',
      chunkFilename: '[id].[contenthash:8].css',
    }),
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          filename: '[name].[chunkhash:8].js',
        },
      },
    },
  },
}

注意事项

  1. 确保在生产环境中使用文件指纹
  2. 合理设置 hash 长度,通常 8 位就足够了
  3. 注意文件指纹对开发环境的影响,建议在开发环境禁用文件指纹
  4. 使用 clean-webpack-plugin 清理旧的构建文件
  5. 合理配置 splitChunks 优化代码分割

开发环境配置

javascript
// webpack.dev.js
module.exports = {
  mode: 'development',
  output: {
    filename: '[name].js', // 开发环境不使用文件指纹
    path: path.resolve(__dirname, 'dist'),
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css', // 开发环境不使用文件指纹
    }),
  ],
}

通过合理使用文件指纹,可以:

  1. 优化浏览器缓存策略
  2. 提高页面加载速度
  3. 确保用户始终使用最新的文件版本
  4. 减少不必要的网络请求