稀土掘金技术社区 09月18日 10:37
Webpack Externals 配置优化项目打包
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何利用 Webpack 的 `externals` 配置来优化项目打包。通过将大型依赖库(如 Element UI 和 Echarts)从打包中排除,并采用 CDN 引入的方式,可以显著减小最终的 bundle 体积,从而提升页面加载速度。文章详细阐述了 `externals` 的配置方法、CDN 的引入步骤,并结合 `webpack-bundle-analyzer` 工具进行分析。此外,还探讨了 Nginx gzip 压缩、Vue 项目的 gzip 配置、路由按需加载、prefetch 策略的调整以及 `splitChunks` 配置等多种优化手段,旨在帮助开发者实现首屏加载时间在 3 秒内的目标。

📦 **利用 `externals` 配置和 CDN 优化打包:** 文章强调了 `externals` 配置的核心作用,即声明某些依赖不应被打包进最终的 bundle,而是从外部环境(如 CDN)获取。通过将 Element UI 等大型库卸载后通过 CDN 引入,并配置 `vue.config.js` 中的 `externals: { 'element-ui': 'ELEMENT' }`,可以有效减小项目体积。同时,文章详细指导了如何在 `public/index.html` 中引入 CDN 链接,并指出需要将库的全局变量名(如 'ELEMENT')与 CDN 引入时暴露的全局变量对应起来。

🚀 **多维度性能优化手段:** 除了 `externals`,文章还全面介绍了其他性能优化方法。包括使用 `webpack-bundle-analyzer` 分析打包体积,识别瓶颈;配置 Nginx 的 `gzip` 压缩以及 Vue 项目的 `compression-webpack-plugin` 以减小传输数据量;实现路由的按需加载(动态导入),确保首页只加载核心代码;合理配置 `prefetch` 策略,平衡带宽消耗与用户体验;以及利用 `splitChunks` 将 `node_modules` 中的依赖单独打包,优化缓存利用率。

💡 **详细的实践指导与注意事项:** 文章提供了具体的代码示例和操作步骤,例如如何安装和配置 `webpack-bundle-analyzer`,如何在 `vue.config.js` 和 `public/index.html` 中进行配置,以及如何查找库的全局变量名。同时,也提醒了版本匹配问题(如 `compression-webpack-plugin`)和 CDN 引入时全局变量名的准确性,确保优化措施能够顺利实施并达到预期效果。

原创 jack_po 2025-09-18 08:30 重庆

Webpack 的 externals 配置用于声明某些依赖应该从外部获取,而不是打包到最终的 bundle 中。这样可以减小打包体积,前提是这些依赖已经在运行环境中存在。

点击关注公众号,“技术干货” 及时达!

有一天,甲方打开一个后台管理的项目,说有点卡,不太满意,项目经理叫我优化,重新打包一下。

从输入地址到 展示 首屏,最佳时间在 3 秒内,否则甲方挂脸,咱就有可能有被裁的风险,understand?

废话不多说,先来看一下怎么个优化法吧。

优化✅ cdn分析用 Webpack Bundle Analyzer 分析依赖,安装 webpack-bundle-analyzer 打包分析插件:

    # NPM
    npm install --save-dev webpack-bundle-analyzer

      # Yarn
      yarn add -D webpack-bundle-analyzer

      反正都是装,看着来。

      配一下:

      // vue.config.js 文件里。(没有就要新建一下)

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

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

        打包执行打包命令并查看分析

          npm run build --report

          打包结束后,会在项目根目录下生成 dist 文件。自动跳到127.0.0.1:8888(没有跳的话,手动打开 dist 文件夹下的 report.html),这个网址就是打包分析报告

          占得比较大的块,就是 Element UI 组件库和 echarts 库占的空间比相对较大。

          这就要考虑,第一,要按需,要啥再用啥,不要一股脑啥都装。按需安装,按需加载。

          第二,考虑单独引入这些组件库的cdn,这样速度也会咔咔提升。

          详细讲一下怎么搞cdn

          按需大家都知道,要啥再引入啥,再装啥。

          比如element-ui,我要uninstall掉,然后呢,去引入 cdn,不要装库了,用 cdn。

          package.json里面看element-ui装了啥版本,然后看完之后,就npm uninstall element-ui卸载掉。

          去 cdn 库里面去找https://www.staticfile.org/,(首先先说一下,要找免费的开放的那种,因为一般有的公司没有自家的 cdn,没有自家的桶,有的话,直接把 js 文件地址拖上去,然后得到一个地址,这样也安全,也方便,但没有的话另说)。

            样式库: https://cdn.staticfile.org/element-ui/2.15.12/theme-chalk/index.min.css 
            组件库:https://cdn.staticfile.org/element-ui/2.15.12/index.min.js

            然后去public/index.html入口文件中,去加入这个东西,像咱以前写原生一样引入就好, body 里面引入 js,head 里面引入 css。:

              <head>
              <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.12/theme-chalk/index.min.css">
              </head>

              <body>
              <script src="https://cdn.staticfile.org/element-ui/2.15.12/index.min.js"></script>
              </body>

              所以这样子,就引入好了。接着在main.js里面,把之前import的所有element的样式删掉。

              接着,vue.config.jsconfigureWebpack加个externals字段:

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

                module.exports = {
                  plugins: [
                    new BundleAnalyzerPlugin()
                  ],
                  externals: {
                    'element-ui''ELEMENT' // key 是之前install下下来的包名,element-ui。value是全局变量名(ELEMENT)
                  }
                }

                「externals」: Webpack 的 externals 配置用于声明某些依赖应该从外部获取,而不是打包到最终的 bundle 中。这样可以减小打包体积,前提是这些依赖已经在运行环境中存在。

                'element-ui': 'ELEMENT' 的含义」

                当你的代码中 import 'element-ui' 时,Webpack 不会打包 element-ui,而是会从全局变量 ELEMENT 中获取它。

                ELEMENT 是 element-ui 库通过 <script> 标签引入时,在全局(window)中暴露的变量名。例如,如果你在 HTML 中这样引入:

                   <script src="https://unpkg.com/element-ui/lib/index.js"></script>

                  那么 element-ui 会挂载到 window.ELEMENT 上。

                  「为什么这样配置?」

                  通常是为了通过 CDN 引入 element-ui(而不是打包它),从而优化构建速度和体积。

                  你需要确保在 HTML 中通过 <script> 提前加载了 element-ui,否则运行时 ELEMENT 会是 undefined

                    <!-- HTML 中通过 CDN 引入 element-ui -->
                    <script src="https://unpkg.com/element-ui/lib/index.js"></script>

                      // webpack.config.js
                      module.exports = {
                        externals: {
                          'element-ui''ELEMENT' // 告诉 Webpack:import 'element-ui' 时,返回全局的 ELEMENT
                        }
                      };

                        // 你的代码中依然可以正常 import(但实际用的是全局变量)
                        import ElementUI from 'element-ui';
                        // 相当于:const ElementUI = window.ELEMENT;

                        「注意事项:」

                        确保全局变量名(ELEMENT)和 element-ui 的 CDN 版本一致。不同版本的库可能有不同的全局变量名。

                        如果使用模块化打包(如 npm + Webpack 全量打包),则不需要配置 externals

                        这里有的伙伴就说,我咋知道是ELEMENT,而不是element呢。

                        这里是这么找的:

                        直接在浏览器控制台检查 在 HTML 中通过 CDN 引入该库:

                          <script src="https://cdn.staticfile.org/element-ui/2.15.12/index.min.js"></script>

                          打开浏览器开发者工具(F12),在 Console 中输入:

                            console.log(window);

                            然后查找可能的全局变量名(如 ELEMENT、ElementUI 等)。

                            cdn 配置之后,重新分析

                              npm run build --report

                              重新用cdn的去分析,

                              那么就很舒服了,也因此,这个就是 cdn 优化的方法。

                              ✅ nginx gzip 压缩

                                server {
                                        listen       8103;
                                        server_name  ************;
                                # 开启gzip
                                   gzip on;
                                   # 进行压缩的文件类型。
                                  gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
                                   # 是否在http header中添加Vary: Accept-Encoding,建议开启
                                   gzip_vary on;
                                }

                                ✅vue gzip 压安包:npm i compression-webpack-plugin@1.1.12 --save-dev

                                注意版本匹配问题。

                                vue 配置,这段配置是 Webpack 构建中关于 「Gzip 压缩」 的设置,位于 config/index.js 文件中。:

                                  //文件路径  config --> index.js
                                  build: {
                                    productionGziptrue// 启用生产环境的 Gzip 压缩
                                    productionGzipExtensions: ['js''css'], // 需要压缩的文件类型
                                  }

                                  productionGzip: true

                                  作用:开启 Gzip 压缩,减少静态资源(JS、CSS)的体积,提升页面加载速度。

                                  要求:需要安装 compression-webpack-plugin(如注释所述)。

                                      npm install --save-dev compression-webpack-plugin

                                  productionGzipExtensions: ['js', 'css']

                                  指定需要压缩的文件扩展名(默认压缩 JS 和 CSS 文件)。

                                  「为什么需要 Gzip?」

                                  「优化性能」:Gzip 压缩后的资源体积可减少 60%~70%,显著降低网络传输时间。

                                  「服务器支持」:大多数现代服务器(如 Nginx、Netlify)会自动对静态资源进行 Gzip 压缩,但本地构建时提前生成 .gz 文件可以避免服务器实时压缩的开销。

                                  ✅ 按需加载路由路由级代码分割(动态导入)

                                  // 原写法
                                  import About from './views/About.vue'

                                  // 优化后写法
                                  const About = () => import(/* webpackChunkName: "about" */ './views/About.vue')

                                  首页只加载核心代码(home 路由)

                                  about 模块会在用户点击 about 路由时才加载

                                  显著减少首屏加载资源体积

                                  ✅ 合理配置 prefetch 策略

                                  // vue.config.js
                                  module.exports = {
                                    chainWebpackconfig => {
                                      // 移除prefetch插件
                                      config.plugins.delete('prefetch')

                                      // 或者更精细控制
                                      config.plugin('prefetch').tap(options => {
                                        options[0].fileBlacklist = options[0].fileBlacklist || []
                                        options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
                                        return options
                                      })
                                    }
                                  }

                                  「禁用 prefetch」:减少不必要的带宽消耗,但可能增加后续路由切换等待时间

                                  「启用 prefetch」:利用浏览器空闲时间预加载,提升用户体验但可能浪费带宽

                                  「折中方案」:只对关键路由或高概率访问的路由启用 prefetch

                                  ✅splitChunks 将 node_modules 中的依赖单独打包「拆分 vendor」:将 node_modules 中的依赖单独打包

                                  config.optimization.splitChunks({
                                   chunks'all',
                                   cacheGroups: {
                                     vendors: {
                                       name'chunk-vendors',
                                       test: /[\\/]node_modules[\\/]/,
                                       priority: -10,
                                       chunks'initial'
                                     }
                                   }
                                  })

                                  ✅ 按需引入 lodash

                                  import debounce from 'lodash/debounce'

                                  用啥再引啥。

                                  甲方笑了打开首页闪电一进,完美 ending!!!

                                  散会啦😊

                                  AI编程资讯AI Coding专区指南:https://aicoding.juejin.cn/aicoding

                                  ""~

                                  阅读原文

                                  跳转微信打开

                                  Fish AI Reader

                                  Fish AI Reader

                                  AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

                                  FishAI

                                  FishAI

                                  鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

                                  联系邮箱 441953276@qq.com

                                  相关标签

                                  Webpack externals CDN 性能优化 打包 前端 Element UI gzip 按需加载 Webpack Externals CDN Performance Optimization Bundling Frontend Lazy Loading
                                  相关文章