为何未配置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文件。要让它使用预压缩文件,需要做两处配置:
- 确保
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时才保留压缩文件 })
- 修改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
相关产品推荐
相关产品推荐

