首页 > 其他分享 >【Webpack】如何做打包优化,才能有效减少包体积

【Webpack】如何做打包优化,才能有效减少包体积

时间:2024-11-26 09:35:02浏览次数:10  
标签:Vue CDN webpack js Webpack 体积 打包 页面

前言

        在一些大型项目中,前端代码在build之后得到的产物有时会非常大,大大影响我们应用上线后的用户体验。Webpack作为当下非常流行的打包工具(作者使用Webpack5),站在前端的角度,去减少build产物体积将是一个绕不开的话题,旨在提升我们Web应用的性能。本文讲根据作者实践经验,分享几种十分有效的优化方式,能够在短时间内得到高成效。

分析打包结果

        我们在解决问题之前需要先分析问题,这里我们使用webpack-bundle-analyzer插件对构建产物进行分析。他是一个专门用来分析打包结果的可视化插件工具,以清晰的图像方式呈现,能够辅助我们去分析优化点。首先使用包管理器对插件进行安装。

npm i webpack-bundle-analyzer -D

        我这里使用的是vue-cli,打开vue-config.js。将webpack-bundle-analyser插件引入并合并到webpack默认配置中。(推荐分文件维护开发环境和生产环境的做法)

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  configureWebpack: {
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }
};

        执行npm run build命令,会自动打开一个网页,看到类似如下的效果。其中最大的chunk-vendors.js里边主要是node_moudules,主要是我们打包后依赖的第三方库;右边主要是以main.js为入口打包src后的代码。

        这就是webpack-bundle-analyser插件对打包结果的可视化展现,其中2.92MB是代码打包后的大小。打包后的dist文件有足足26.6MB(包括图片等资源)。

        对此情况展开分析,可以发现:

  • ElementUI、lodash库占有很大空间,都被打包进去了,这部分代码是可以放在cdn去管理的,可以解放我们打包后的代码。
  • 该应用有多个页面,如果直接加载岂不是没有必要,可以使用分包的方式处理。
  • 页面中存在一些图片资源,占总体积的90%以上,这部分需要制定策略,将一部分较小的图片转化成base64格式。

使用CDN

        CDN叫做“内容分发网络”,如果放定制的资源到CDN上一般是要收费的,领导一般对成本比较敏感,没有太大的必要可以不选择这种方式;比较建议的是一些相对稳定的免费CDN,一些公共开放的资源如Vue、Vuex、Vue-Router、ElementUI、lodash、axios可以使用,能够加速资源的访问。

        CDN服务器一般有专门的厂商维护,具有较高的稳定性,有些支持HTTP2协议,我们使用CDN一定程度上能够吃到一些传输效率的福利。

寻找CDN

        寻找CDN一定要寻找安全可靠的,我这里使用BootCDN,属于人气很高的免费CDN加速服务。接下来去寻找Vue、Vuex、ElementUI这些地址。可查看package.json对应寻找,尽量寻找带.min后缀的,压缩后的js体积更小。

引用CDN

        找到对应的CDN后,复制标签粘贴到public/index.html中。注意:

  • public/index.html在打包中会被webpack识别,被html-webpack-plugin读取,因此可以借助模板引擎提供的判断,只需在生产环境被引入。
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet">
    <% if(NODE_ENV === 'production') { %>
    <link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css" rel="stylesheet">
    <% } %>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <% if(NODE_ENV === 'production') { %>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.1/vue-router.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js"></script>
    <% } %>
  </body>
</html>
  • 使用script引入静态js,会在全局注册对象,像Vue.use/install这类方法在生产环境中就不再适用,因此需要做一些兼容。
if (!window.VueRouter) {
  Vue.use(VueRouter)
}

if (!window.Vuex) {
  Vue.use(Vuex)
}

if (!window.ELEMENT) {
  Vue.use(ElementUI)
}

忽略资源打包

        既然用CDN的方式引用了,那么在webpack打包时就不再需要将这些依赖加入任务中,需要忽略这些依赖。找到webpack配置,加入externals。(这里简单区分一下环境,建议分文件管理)

const WebpackCommonConfigs = {
  transpileDependencies: true,
};

// 生产环境
if (process.env.NODE_ENV === 'production') {
  module.exports = defineConfig({
    ...WebpackCommonConfigs,
    configureWebpack: {
      plugins: [
        new BundleAnalyzerPlugin()
      ],
      externals: {
        vue: 'Vue',
        'element-ui': 'ELEMENT',
        vuex: 'Vuex',
        'vue-router': 'VueRouter',
      }
    }
  });
} else { // 开发环境
  module.exports = defineConfig({
    ...WebpackCommonConfigs,
  });
}

        然后我们build一下,发现我们引用CDN后将外部依赖相关代码从2.92MB减小到283.03KB,体积减小了1000%,效果非常明显,可见第三方依赖库体积有多庞大。

页面分包处理

        我们这里的策略是路由懒加载,目的是让页面和页面之间分成不同的chunk动态加载,在A页面时不用去读取B页面相关的资源,提升性能也提升用户体验。怎么做呢?非常简单!去寻找router中每个注册页面或子页面,将其改写成以下形式。

component: () => import('./general/Index.vue')

        执行build不难看出,不同页面被打包成了不同的css和js, 目的达成!

        可以使用注释让webpack识别,从而去自定义打包后的chunk名。 

component: () => import(/* webpackChunkName: "general" */'./general/Index.vue')

图片资源优化

  • 对静态图片资源进行压缩,提升渲染速率。
  • 设置小于200kb的图片转化为Base64格式,减少小图片形成的多请求的情况。

图片压缩

        这里使用image-webpack-loader,安装后将配置注入到vue-config.js中,设置匹配文件名、jpeg和png压缩质量等配置。

module: {
  rules: [{
    test: /\.(gif|png|jpe?g|svg)$/i,
    use: [
      {
        loader: 'image-webpack-loader',
        options: {
          mozjpeg: {
            progressive: true,
            quality: 60,
          },
          pngquant: {
            quality: [0.65, 0.70],
            speed: 4
          },
        }
      },
    ],
  }]
}

Base64转化 

        对小于200KB的图片转化Base64。

module: {
  rules: [
    {
      test: /\.(gif|png|jpe?g|svg)$/i,
      type: "asset",
      parser: {
        dataUrlCondition: {
          maxSize: 200 * 1024  // 小于200kb大小的图片转base64格式
        }
      },
      generator: {
        filename: "img/[hash:7][ext]"
      }
    },
  ]
}

 

移除源码地图

        再次查看dist目录,发现打包过后的js都存在一个对应的.map文件,这种文件叫做源码地图,用来反解析被处理过的代码。当build后,webpack会对代码进行合并、压缩、混淆等,可读性变得极差,有源码地图就能够反向解析压缩后的代码,以便于调试定位有问题的代码。

         生产环境中,源码地图的存在不仅会使打包体积增大,更重要是会威胁到应用的安全性。去掉源码地图的方法极其简单,将devtool设为false就可以了。

configureWebpack: {
      devtool: false,
}

总结

        经过上述优化,我们打包再看看大小,发现dist大小只有11MB了,从26.6MB优化到了11MB,用数据量化就是减少了240%的体积。

         利用performance工具查看LCP(最大内容绘制)参数,这个指标是用户能够看到的最大内容。为了使数据更加合理,我从大约30条同环境下数据中选择的中位数。最终经过计算得出LCP提升了28%,究其原因,主要是对静态图片做了压缩和Base64转化,在图片过大导致渲染时间长的问题上得到了较大的提升。因为页面较为简单,所以提升的幅度有限。能够控制在2.5s之内,是LCP指标定义的良好范围。

        打包优化,减少包体积的方法远远不止这些,还有像Gzip压缩、代码删减、兼容性策略等。实际应用中,上述方法可谓工作量不大且效果明显,性价比很高。 看到这里,如果对您有帮助的话可以点个关注哦!当然如果有什么好的意见或者建议也可以在评论区交流或者私信。

标签:Vue,CDN,webpack,js,Webpack,体积,打包,页面
From: https://blog.csdn.net/mayuhao0000/article/details/143991216

相关文章

  • Nuxt.js 应用中的 webpack:error 事件钩子
    title:Nuxt.js应用中的webpack:error事件钩子date:2024/11/25updated:2024/11/25author:cmdragonexcerpt:webpack:error钩子是用于在Webpack编译过程中捕获和处理错误的一个重要机制。当发生编译错误时,这个钩子会被调用,通常用于在UI上给出反馈或者处理错误日志......
  • 第5天:基础入门-APP应用&微信小程序&原生态开发&H5+Vue技术&封装打包&反编译抓包点
    #知识点1、基础入门-APP应用-开发架构安全问题2、基础入门-小程序应用-开发架构安全问题一、APP应用开发架构:1、原生开发安卓一般使用java语言开发,当然现在也有kotlin语言进行开发。如何开发就涉及到具体编程了,这里就不详说了。简单描述就是使用安卓提供的一系列......
  • 利用1panel部署前后端分离项目 Java代码打包 前端打包
    初次发布于我的个人文档参考:1.1Panel官方文档本文介绍一下如何利用1panel部署一个简单的前后端分离项目。1,拥有一个Liunx服务器第一步是购买一个Linux服务器,可以买一台线下真实的机器+公网IP或买一个阿里云、腾讯云、京东云、华为云服务器。2.安装1panel参考1panel官方文......
  • 将字体打包至Docker中使用解决文字替换乱码问题
    1.将字体文件放在font文件夹下上传至发布文件夹(一般是:/www/wwwroot/xxx.com/publish)中。 2.编辑Dockerfile文件,增加: #复制本地字体文件到容器内的字体目录COPY./font//usr/share/fonts/truetype/custom/ 其中,“./font/ ”是字体文件所在文件夹,/usr/share/fonts/tr......
  • dsl 在打包构建生成代码中,是哪个英文单词的缩写
    在打包构建生成代码的上下文中,DSL通常是"Domain-SpecificLanguage"的缩写。Domain-SpecificLanguage(领域特定语言)DSL是一种计算机语言或规格,专门为解决特定领域的问题而设计。与通用编程语言(如Java、Python)不同,DSL专注于某一特定的应用领域,使得该领域的专家能够更容......
  • Qt 打包为可执行文件(详解)
    https://blog.csdn.net/dfr110719/article/details/136992619<divid="content_views"class="htmledit_views"><pid="main-toc"><strong>目录</strong></p>一.打包为文件夹二.打包为可执行......
  • Nuxt.js 应用中的 webpack:change 事件钩子
    title:Nuxt.js应用中的webpack:change事件钩子date:2024/11/24updated:2024/11/24author:cmdragonexcerpt:通过webpack:change钩子,开发者可以知道哪些文件被修改,并可以进行适当的处理,比如重新加载相关模块,或更新用户界面等。categories:前端开发tags:Nuxt.js......
  • webpack基础配置
    文章目录一、默认入口和默认出口二、资源配置三、输出文件3.1多文件入口3.2HtmlWebpackPlugin插件四、环境4.1环境变量4.2热更新五、代码分离5.1公共模块5.2懒加载5.3预获取/预加载模块六、缓存七、TreeShaking八、公共路径webpack是一个用于现代JavaSc......
  • Unity资源打包之Asset Bundle
    AssetBundle的作用:1.AssetBundle是一个压缩包包含模型、贴图、预制体、声音、甚至整个场景,可以在游戏运行的时候被加载;2.AssetBundle自身保存着互相的依赖关系;3.压缩包可以使用LZMA和LZ4压缩算法,减少包大小,更快的进行网络传输;4.把一些可以下载内容放在AssetBundle里面,可以......
  • Ubuntu虚拟机&conda虚拟环境运行和打包引入SimNIBS软件包的python项目文件
    项目背景:项目是python代码写的,其中有一个模块SimNIBS不能通过pip安装,需要自己下载软件包,在Ubuntu虚拟机的虚拟环境中运行和打包。下面是整个流程和遇到的一些问题,写下来做个记录。(默认此时SimNIBS已经安装好了,还没安装好的话,参见文章Ubuntu虚拟机安装医学影像软件包SimNIBS及报......