【前端】性能优化——webpack 打包压缩

今天偶然发现,打开自己的博客网站时特别慢,

可以看到其中一个js下载了11s才下载完,有2.6MB(这还是nginx做了gzip压缩之后的大小),nginx压缩前的大小如下:

可以看到这个js竟然高达10MB,才想起来,我忘记做webpack的打包压缩了。OK,优化走起:

一、下载压缩相关的库

# js 压缩
npm install uglifyjs-webpack-plugin --save-dev
# css提取
npm install mini-css-extract-plugin --save-dev
# css压缩
npm install css-minimizer-webpack-plugin --save-dev
# 读取环境变量
npm install cross-env --save-dev

二、配置 webpack.config.js[2023-02-16更新]

const path = require("path")
const webpack = require("webpack")
const HtmlWebpackPlugin = require('html-webpack-plugin') // 生成html入口文件
const {CleanWebpackPlugin} = require('clean-webpack-plugin') // 编译文件时,清理 build/dist 目录,再生成新的

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');


const isProduction = process.env.NODE_ENV === "production"
const isDevelopment = process.env.NODE_ENV === "development"
console.log("print env: ", isProduction)

module.exports = {
    entry: {
        app: path.resolve(__dirname, "src/index.tsx"),
    },
    mode: "development",
    module: {
        rules: [
            {
                test: /\.(js|jsx|ts|tsx)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: [
                                [
                                    "@babel/preset-env",
                                    // 配置信息
                                    {
                                        targets: {
                                            "chrome": "58",
                                            "ie": "11",
                                        },
                                        // 指定 corejs 的版本
                                        "corejs": "3",
                                        // 使用 corejs 的方式 "usage" 表示按需加载
                                        "useBuiltIns": "usage"
                                    }
                                ],
                                [
                                    "@babel/preset-typescript",
                                ],
                                [
                                    "@babel/preset-react",
                                    {}
                                ]
                            ]
                        }
                    },
                    {
                        loader: "ts-loader" // 1. 先加载ts
                    }
                ],
            },
            {
                test: /\.(css|scss)$/,
                use: [

                    {
                        loader: process.env.NODE_ENV === "production"
                            ? MiniCssExtractPlugin.loader // 提取css到文件中,放到head中
                            : "style-loader", // 4. 加载样式文件到head

                    },
                    {
                        loader: "css-loader", // 3. 加载css
                        options: {
                            importLoaders: 1,
                            sourceMap: true
                        }
                    },
                    {
                        loader: "postcss-loader", // 2. 加载postcss(项目里配置的是 autoprefixer 和 px2rem) 转换 css里的rem和厂商前缀
                        options: {
                            postcssOptions: {
                                config: path.resolve(__dirname, 'postcss.config.js')
                            },
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader", // 1. 加载 scss 转换成css
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            },
            // {
            //     test: /\.(png|jpg|gif)$/,
            //     use: [
            //         {
            //             loader: 'file-loader',
            //             options: {
            //                 name: '[sha512:hash:base64:7].[ext]'
            //             }
            //         }
            //     ]
            // } // by junfenghe 2021-12-06
            {
                test: /\.(png|jpg|gif|ico)$/,
                type: 'asset/resource',
                generator: {
                    filename: 'static/media/[hash][ext][query]'
                }
            },
            {
                test: /\.svg/,
                type: 'asset/inline'
            },
            // 20230216 打包html中的图片
            {
                test: /\.(htm|html)$/i,
                loader: "html-withimg-loader"
            }
            // {
            //     test: /\.(txt|pdf|excel)$/,
            //     type: 'asset/source'
            // }
        ]
    },
    resolve: {
        extensions: ["*", ".js", ".jsx", ".ts", ".tsx"], // 尝试按顺序解析这些后缀名。能够用户再引入模块时不带扩展,例如:import File from '../path/to/file'
    },
    output: {
        path: path.resolve(__dirname, "build"), // 文件输出的路径
        // filename: "bundle.js", //对于单一入口(entry point)起点,filename 会是一个静态名称;
        filename: "static/js/[name].[fullhash].bundle.js", // 决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。// 当通过多个入口起点(entry point)、代码拆分(code splitting)或各种插件(plugin) 创建多个 bundle,应该赋予每个 bundle 一个唯一的名称
        assetModuleFilename: "images/[hash][ext][query]" // by junfenghe 2021-12-06 // by junfenghe 20221228
    },
//20230216
    optimization: {
        minimizer: [
            // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
            `...`,
            new CssMinimizerPlugin({
                parallel: true,//使用多进程并发执行,
                minimizerOptions:{
                    preset:[
                        "default",
                        {
                            discardComments: {removeAll:true},//移除所有注释
                        },
                    ]
                }
            }),
        ]
    },
//20230216
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'public/index.html')
        }),
        new CleanWebpackPlugin({
            path: path.join(__dirname, 'build')
        }),
        //         // 20230216 代码压缩
        // new UglifyJsPlugin({
        //     parallel: true,// 使用多进程并行以提高构建速度
        //     sourceMap: true,// 使用源映射将错误信息位置映射到模块(这将会减慢编译速度)。
        //     // extractComments:true,//启用禁用提取注释
        //     cache: true,//启用缓存
        //     uglifyOptions: {
        //         comments: false,//如果你构建时不想出现注释,可以按照以下配置将 uglifyOptions.output.comments 设置为 false:
        //     },
        // }),
        // // 提取css
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename: 'static/css/[name].[contenthash:8].css',
            chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
        }),
        new CssMinimizerPlugin()

    ],
    devServer: {
        static: {
            directory: path.join(__dirname, "public")
        },
        historyApiFallback: true, //When using the HTML5 History API, the index.html page will likely have to be served in place of any 404 responses. Enable devServer.historyApiFallback by setting it to true:
        port: 3003,
        compress: true
    },
    devtool: isProduction?false:'source-map',//生产环境关闭sourcemap
}

if (isProduction) {
    pluginsProduction = [
        // 20230216 代码压缩
        new UglifyJsPlugin({
            parallel: true,// 使用多进程并行以提高构建速度
            sourceMap: true,// 使用源映射将错误信息位置映射到模块(这将会减慢编译速度)。
            // extractComments:true,//启用禁用提取注释
            cache: true,//启用缓存
            uglifyOptions: {
                comments: false,//如果你构建时不想出现注释,可以按照以下配置将 uglifyOptions.output.comments 设置为 false:
            },
        }),

    ]
    module.exports.plugins.push(
        ...pluginsProduction
    )

}

三、基于 React.lazy() 的优化

原来的代码:

import DimensionReading from "../../pages/dimension/dimension-reading/dimension-reading";
import DimensionWriting from "../../pages/dimension/dimension-writing/dimension-writing";
import DimensionPhoto from "../../pages/dimension/dimension-photo/dimension-photo";
import DimensionPlan from "../../pages/dimension/dimension-plan/dimension-plan";
import DimensionAdd from "../../pages/dimension/dimension-add/dimension-add";
import DimensionHome from "../../pages/dimension/dimension-home/dimension-home";
import SelfIntro from "../../pages/self-intro/self-intro";

优化后的代码:

const DimensionReading = lazy(() => import("../../pages/dimension/dimension-reading/dimension-reading"))
const DimensionWriting = lazy(() => import("../../pages/dimension/dimension-writing/dimension-writing"))
const DimensionPhoto = lazy(() => import("../../pages/dimension/dimension-photo/dimension-photo"));
const DimensionPlan = lazy(() => import("../../pages/dimension/dimension-plan/dimension-plan"));
const DimensionAdd = lazy(() => import("../../pages/dimension/dimension-add/dimension-add"));
const DimensionHome = lazy(() => import("../../pages/dimension/dimension-home/dimension-home"));
const SelfIntro = lazy(() => import("../../pages/self-intro/self-intro"));
  • React Lazy 是一个 React 的高级特性,可以使得在使用 Webpack 或者其他打包工具进行构建时,能够按需加载组件,从而减少首次加载页面的时间和网络流量。React Lazy 配合 React Suspense 一起使用可以实现更好的体验。
  • 这是webpack打包之后的效果,可以看到:每个使用lazy()高级特性的组件,都能独立打包,网页加载时也就达到了按需加载的目的了。

四、查看优化效果

优化完,直接打包之后的大小如下:

  • 可以看到最大的这个js从10MB变成了4MB,接着看部署之后的实际效果:
  • 可以看到,经过nginx的gzip压缩之后,从原先的2.6MB,变成了1.3MB。

五、总结

写到这儿,打包压缩的性能优化已经告一段落了,这块其实以前也做过一点,现在也算回顾了一下,接下来可以把一些静态文件(包括js、css、img等等)上传至cdn,来进一步加速,各位友友有其他性能优化的建议,也可以一起交流一波,互相学习学习!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了优化前端性能,Webpack可以采取多种措施。首先,通过代码压缩、合并和缓存控制,可以减少文件大小并提高加载速度。例如,可以使用Webpack压缩插件(如UglifyJS)来压缩JavaScript代码,并使用提取公共代码的功能来减少重复代码的加载。这样可以减小文件体积并提升页面加载速度。 其次,Webpack还支持使用ES6或CoffeeScript等高级语言来编写源码,并将其构建成浏览器支持的ES5代码,从而提高开发效率和代码质量。这可以通过使用Babel等工具和Webpack的loader来实现。 此外,Webpack还支持CSS的压缩。可以使用插件(如css-minimizer-webpack-plugin)来去除无用的空格,减小CSS文件的大小。这样可以提高页面的加载速度。 最后,对于HTML文件,Webpack也可以进行压缩。可以使用插件(如html-minimizer-webpack-plugin)来去除HTML文件中的无用空格、注释等,从而减小文件大小。这样可以加快页面加载速度。 综上所述,通过使用Webpack的各种优化手段,可以有效地提升前端项目的性能,加快页面加载速度,提高用户体验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【前端知识之webpackwebpack如何优化前端性能](https://blog.csdn.net/weixin_44337386/article/details/125845074)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [webpack学习教程之前端性能优化总结](https://download.csdn.net/download/weixin_38656364/14902051)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值