webpack打包优化之外部扩展externals的实际应用

2020-01-17 23:21:54

参考地址 webpack打包优化之外部扩展externals的实际应用

前言

使用vue-cli创建项目,使用webpack打包。其中,有一个webpack优化webpack.optimize.CommonsChunkPlugin,它会将node_modules中的必需模块提取到vendor文件中,项目开发中,增加第三方模块,比如element-uivue-echarts等,vendor的包都会增大。这个时候,就需要考虑减轻vendor包的大小,增加构建速度。我们可以使用webpack的外部扩展(externals)功能。

externals定义

externals配置选项,将指定的内容排除在构建的vendor中,但是,指定的内容需要出现在用户环境中。
以上是我的理解。

官方解释是:
The externals configuration option provides a way of excluding dependencies from the output bundles. Instead, the created bundle relies on that dependency to be present in the consumer's environment.
externals配置选项提供了「从输出的 bundle 中排除依赖」的方法。相反,所创建的 bundle 依赖于那些存在于用户环境(consumer's environment)中的依赖。

用法

防止将某些 import的包打包到bundle中,而是在运行时(runtime)再去外部获取这些扩展依赖(external dependencies)
可以通过多种编写方式实现:string,array,object,function,regex。这里,我只说一些简单的内容,详细讲解,我觉得这个解释不错。

module.exports = {  // ...
  externals: [ // array形式
    { // object形式
      './a', 'a', // string形式
      jquery: 'jQuery', 
      vue: 'Vue',
    },    function(context, request, callback) { // function形式
      if(request.substr(0, 1) !== '.') callback(null, 'commonjs ' + request)
      callback()
    },
    /^[a-z\-0-9]+$/, // regex形式
  ]
}

除了function形式,必须在array形式中,其他形式,都可以提升,直接作为externals属性使用。比如string形式:

externals: {    './a': 'a',    jquery: 'jQuery'}

string

属性名称是jquery,表示应该排除import $ from 'jquery'中的 jquery模块。为了替换这个模块,jquery的值将被用来检索一个全局的$变量。换句话说,当设置为一个字符串时,它将被视为全局的,我们需要在全局变量中,找到$,才能使程序正确运行。

array

数组内的每一个元素都可以是多种形式,包括objectregexfunctionstring四种:

object

object形式,可以直接作为externals的值,这种形式是绝大部分项目中的配置形式。它里面一定是键值对(key: value)的形式。

function

function的使用,只能在array形式中作为一个元素传入。

regex

正则匹配的形式,通过传入正则表达式来实现匹配。这个可以放在数组形式中,也可以直接作为externals的属性。

实际案例

案例地址
以上说了如何配置的问题,在工作中,具体会是一个怎样的表现呢。我挑选了一个常用的配置object形式,做了一些操作,对比下。

  • 第一种情况,完全不使用externals配置。
    第一种情况的截图
    first build
    first browser load

  • 第二种情况,通过npm run build --report得出的报告,将一些不常修改的大包作为外部扩展。
    这需要做两步操作:第一步修改webpack.base.conf.js文件,第二步,将外部扩展的内容通过其他方式加载到window环境,这里,我们通过<script>标签,并使用cdn来完成。
    配置的文件:webpack.base.conf.js

externals: {  vue : 'Vue',  "echarts": 'echarts',  "element-ui": 'ELEMENT'}

在模板文件index.html中,添加<script>标签

<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script><script src="https://unpkg.com/element-ui@2.4.11/lib/index.js"></script><script src="https://unpkg.com/echarts@4.1.0/dist/echarts.min.js"></script>

第二种情况的截图:
second build
second browser load

这两种情况,我们主要从打包的时间,打包之后包的大小,实际浏览器中加载时长三个方面来做比较。

打包时间

打包时间,由原来的38s缩短至18s,大大减少了打包时间。

打包之后包的大小

主要看vendor包的大小,由原来的1.45M缩小至41.3k,缩小的内容,我们使用cdn,使其存在于外部环境。
由于externals属性,是将依赖排除,本该将node_modules中依赖包打入到vendor bundle中,变成外部扩展。

浏览器加载

使用externals属性,外部扩展,会增加请求数,由原来的6个请求变成了9个请求。由于是使用CDN,非首次请求,会使用缓存中的数据,所以加载时间不受太大影响。
截图所示时间不同,这个和多方面因素有关。你在相同的环境,每次刷新得到的结果都不一样。

需要注意

如果发现问题,可以通过以下几个方向查找:

  1. script的先后顺序

  2. cdn的地址路径是否正确

  3. 浏览器的window属性值,是否和你的externals属性的value相对应。可以在console控制台输出看看。

  4. externals的打包支持什么类型的,就和output.libraryTargetoutput.library 这两个属性有关系了。唐霜讲的清楚点,可以看看

参考

  1. 外部扩展Externals

  2. webpack externals详解

  3. 本案例地址


  • 2020-12-16 22:07:44

    Android视频点播-边播边缓存

    一些知名的视频app客户端(优酷,爱奇艺)播放视频的时候都有一些缓存进度(二级进度缓存),qq,微信有关的小视频,还有一些短视频app,都有边播边缓的处理。还有就是当文件缓存完毕了再次播放的话就不再请求网络了直接播放本地文件了。既节省了流程又提高了加载速度。 今天我们就是来研究讨论实现这个边播边缓存的框架,因为它不和任何的业务逻辑耦合。

  • 2020-12-16 22:46:44

    基于coturn项目的stun/turn服务器搭建

    webrtc是google推出的基于浏览器的实时语音-视频通讯架构。其典型的应用场景为:浏览器之间端到端(p2p)实时视频对话,但由于网络环境的复杂性(比如:路由器/交换机/防火墙等),浏览器与浏览器很多时候无法建立p2p连接,只能通过公网上的中继服务器(也就是所谓的turn服务器)中转。示例图如下:

  • 2020-12-16 23:06:05

    Rocket.Chat推送信息

    Rocket.Chat推送消息 Rocket.Chat是一个开源实时通讯平台, 支持Windows, Mac OS, Linux. 支持聊天, 文件上传, 视频通话, 语音通话功能. 向Rocket.Chat推送消息 以下示例可以转为别的语言的版本, 本示例使用Linux平台的curl测试, curl非常强大. 登陆 首先需要登陆Rocket.Chat服务器

  • 2020-12-17 09:01:23

    对BitTorrent Tracker源码分析

    tracker服务器是BT下载中必须的角色。一个BT client 在下载开始以及下载进行的过程中,要不停的与 tracker 服务器进行通信,以报告自己的信息,并获取其它下载client的信息。这种通信是通过 HTTP 协议进行的,又被称为 tracker HTTP 协议,它的过程是这样的: client 向 tracker 发一个HTTP 的GET请求,并把它自己的信息放在GET的参数中;这个请求的大致意思是:我是xxx(一个唯一的id),我想下载yyy文件,我的ip是aaa,我用的端口是bbb。。。

  • 2020-12-17 10:55:48

    html5 video p2p research

    节约带宽,减少缓冲时间,提升服务质量,处理峰值流量, 视频观看的人越多,播放越流畅。

  • 2020-12-17 10:57:34

    使用 MediaSource 搭建流式播放器

    Media Source Extensions(媒体源扩展)大大地扩展了浏览器的媒体播放功能,提供允许JavaScript 生成媒体流。这可以用于自适应流(adaptive streaming,也是我毕设的研究方向)及随时间变化的视频直播流(live streaming)等应用场景。