You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何未配置Compression插件,Webpack 5仍自动压缩Bundle?

关于Webpack 5 React应用Gzip压缩的两个疑问

我司有一个基于Webpack 5的React应用,Webpack配置如下:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require("webpack");
const path = require("path");
const deps = require("./package.json").dependencies;
const dotenv = require("dotenv").config();

module.exports = (env = {}) => {
  const mode = env.NODE_ENV === "prod" ? "production" : "development";

  return {
    entry: "./src/index",
    mode: mode,
    devtool: mode === "production" ? false : "source-map",
    devServer: {
      static: path.join(__dirname, "dist"),
      port: 3000,
      hot: true,
      historyApiFallback: true,
      client: {
        overlay: false,
      },
    },
    resolve: {
      extensions: ['.tsx', '.ts', '.js'], 
    },
    output: {
      publicPath: "/",
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,  // TypeScript loader
          exclude: /node_modules/,
          use: 'ts-loader',
        },
        { test: /\.m?js/, type: "javascript/auto" },
        {
          test: /\.m?js/,
          resolve: {
            fullySpecified: false,
          },
        },
        {
          test: /\.m?js$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-env", "@babel/preset-react"],
              plugins: [
                "@babel/plugin-proposal-class-properties",
                "@babel/plugin-transform-async-to-generator",
                "@babel/plugin-syntax-jsx",
                "@babel/plugin-syntax-dynamic-import",
              ],
            },
          },
        },
        {
          test: /\.scss$/,
          use: [
            mode !== "production"
              ? "style-loader"
              : MiniCssExtractPlugin.loader,
            "css-loader",
            "sass-loader",
          ],
        },
        {
          test: /\.css$/,
          use: [
            mode !== "production"
              ? "style-loader"
              : MiniCssExtractPlugin.loader,
            "css-loader",
          ],
        },
        {
          test: /\.(png|svg|jpg|gif|ico)$/,
          use: ["file-loader"],
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            {
              loader: "file-loader",
            },
          ],
        },
        {
          test: /\.json$/,
          loader: "json-loader",
        },
        {
          test: /\.txt$/i,
          use: "raw-loader",
        },
      ],
    },
    plugins: [
      new ModuleFederationPlugin({
        name: "mainApp",
        library: { type: "var", name: "mainApp" },
        remotes: {
          linkManagement: "linkManagement",
        },
        shared: {
          "react-router-dom": {
            singleton: true,
          },
          "react-dom": {
            singleton: true,
          },
          react: {
            requiredVersion: deps.react,
            singleton: true,
          },
          "component-lib": {
            singleton: true,
          },
        },
      }),
      new HtmlWebpackPlugin({
        template: "./public/index.html",
      }),
      new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].css",
      }),
      new webpack.DefinePlugin({
        VERSION: JSON.stringify("3.0.67"),
        ENV: JSON.stringify(env.NODE_ENV),
        AUTH0_CONFIG_DOMAIN: JSON.stringify(process.env.AUTH0_CONFIG_DOMAIN),
        //some other env vars here
      }),
    ],
  };
};

为优化应用加载速度,我计划给Bundle做Gzip压缩,但遇到两个问题:

  • 构建后dist目录没有.gz后缀的文件,但访问localhost:3000时,main.js的响应头里有Content-Encoding: gzip,按Webpack文档说需要安装compression-webpack-plugin才能压缩,为什么会默认有这个效果?
  • 安装compression-webpack-plugin并配置后,dist目录确实生成了.gz文件,但访问localhost:3000时main.js的大小和加载耗时和之前完全一样,是不是漏了什么配置?

问题1:未安装插件却出现Gzip响应头的原因

这是因为你使用的webpack-dev-server在开发模式下会自动开启实时Gzip压缩,它是在服务器层面动态压缩文件后返回给浏览器的,不会在本地磁盘生成.gz格式的文件。这个默认行为是为了让你在开发阶段就能模拟生产环境的压缩效果,同时避免每次构建都生成压缩文件拖慢开发效率。

问题2:安装插件后加载耗时无变化的解决办法

你虽然生成了预压缩的.gz文件,但webpack-dev-server默认还是会实时压缩原文件返回,不会自动读取预生成的.gz文件。要让它使用预压缩文件,需要做两处配置:

  1. 确保compression-webpack-plugin的配置正确,比如指定要压缩的文件类型:
const CompressionPlugin = require('compression-webpack-plugin');

// 在plugins数组中添加该插件配置
new CompressionPlugin({
  algorithm: 'gzip',
  test: /\.(js|css|html|svg)$/,
  threshold: 8192, // 仅压缩大于8KB的文件
  minRatio: 0.8, // 压缩率低于0.8时才保留压缩文件
})
  1. 修改webpack-dev-server的配置,开启磁盘写入,确保预压缩文件能被dev-server读取:
devServer: {
  // 保留原有配置
  static: path.join(__dirname, "dist"),
  port: 3000,
  hot: true,
  historyApiFallback: true,
  client: {
    overlay: false,
  },
  // 添加以下两项配置
  compress: true,
  devMiddleware: {
    writeToDisk: true, // 让构建文件写入本地dist目录
  },
}

另外,如果是生产环境部署,还需要确保你的静态资源服务器(比如Nginx、Apache)配置了根据请求头的Accept-Encoding返回对应的预压缩文件,而不是实时压缩。比如Nginx需要添加gzip_static on;配置来启用预压缩文件的读取。

内容的提问来源于stack exchange,提问作者d14bl0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:04:51