前言

在5 分钟带你快速读懂 vite 打包过程,源码分析一文中,我们介绍了 vite 打包的代码转化是通过 esbuild 来完成的。而 esbuild 是不支持 ie11 的。所以 vite 的 GitHub 上经常会出现一些 issue 问如何支持 ie11,例如下面这个 issue:

在这个 issue 下,vite 的几位 contributor 分别讲了几种支持 ie11 的解法:

undefin 大佬:我没有这样测过,似乎你需要在 rollupOptions 中添加 babel/polyfill 和添加 umd 格式。

在你的 vite.config.js 中添加以下代码,需要注意的是你要安装 core-js@babel/core@babel/preset-env@babel/runtime

import babel  from '@rollup/plugin-babel';export default {rollupInputOptions: {plugins: [babel({presets: [["@babel/preset-env",{"corejs": 2,"useBuiltIns": "usage","targets": {"ie": "11"}}]]})],}
}

aleclarson 大佬:我做了一个插件 vite-plugin-legacy 用来简单地支持旧的(浏览器)遗留。请等待 #874 合并!

其实相比较这两位大佬的解法,大体上的思路是一样的,都是围绕 babel 来实现代码的转化、贴片操作。但是,如果较起真来,还是 aleclarson 大佬的 vite-plugin-legacy 比较贴心。并且,上面提及的 PR 现在已经合并了,这代表着我们已经可以使用 vite-plugin-legacy 插件了!

需要注意的是,vite-plugin-legacy 的主要实现是基于 configureBuild Hook 实现的,而 configureBuild Hook 是在 vite 的 1.0.0-rc.8 版本以及之后才有的。

那么,进入今天的正题,我将带大家一起欣赏一番 configureBuild 的内部景象(源码)~

configureBuild Hook 介绍

configureBuild Hook 将会在构建功能进行任何操作之前调用。初始化构建配置时,它会被深度拷贝,便于 configureBuild Hook 可以更轻松地对其进行检查和变异(而不需要检查所有未定义的地方)。默认会将 Rollup 的输入(input)选项暴露给 configureBuild,使得 vite 的插件(plugin)能更好地操纵构建过程,并且,意味着更强大的 vite 插件将成为可能。

vite 打包的大致过程如下:

通过图例,我们可以简单了解到 configureBuild Hook 会在打包的最后阶段生成文件到硬盘 时被调用。

使用 configureBuild Hook 自定义插件

首先,我们来看一个使用 configureBuild Hook 的插件示例:

定义插件 myPlugin.ts:

export default (): Plugin => ({configureBuild(viteConfig) {...return async build => {....}}
})

这里,我们定义了一个箭头函数,它会返回 configureBuild 函数,也就是 configureBuild Hook,它会在打包的开始被调用,并且会传入两个参数 configbuilds(在后面,我会一一介绍它们)。而 configureBuild 调用会返回一个 async 函数,它会在打包的结束调用。

配置 vite.config.ts:

import myPlugin from "./myPlugin"
import type { UserConfig } from "vite"const config: UserConfig = {plugins: [myPlugin()]
}export default config

两个步骤,我们就完成了一个的使用 configuredHook Plugin 的简单示例。虽然,知道了怎么定义使用 configureBuild Hook 的 Plugin,但是大家可能会对 configureBuild 的参数 buildconfig 是什么、以及如何应用抱有疑问。

那么,接下来,我们带着这些疑问从源码的角度深入了解一下 configureBuild Hook~

从源码角度认识 configureBuild Hook

configureBuild Hook 会在 build 构建方法的开始被调用,首先会创建一个 builds 数组用于保存每个 configuredBuild Hook 操作结果的 bundle,并且 vite 默认打包生成的 bundle 也会放到 builds 中。

// src/node/build/index build()
const builds: Build[] = []

需要注意的是,并不是 configuredBuild Hook 必须要返回 bundle,也可以不返回。

然后,会对用户传入 configoptions 深度拷贝并填充默认值,这是为了保证后续逻辑的正常进行,而不需要处理不存在某个选项的逻辑,类似于当初 webpack 4 增加了配置默认值一样。

const config = prepareConfig(options)

深度拷贝并填充默认值的实现很简单,首先通过 klona npm 模块来完成对 configoptions 的深度拷贝,然后通过解构赋值的方式设置默认值。

import klona from "klona/json";function prepareConfig(config: Partial<BuildConfig>): BuildConfig {const {alias = {},assetsDir = '_assets',assetsInclude = isStaticAsset,assetsInlineLimit = 4096,...} = klona(config)return {...config,alias,assetsDir,assetsInclude,assetsInlineLimit,base,...}
}

接下来,会从 config 中获取到 configureBuild,由于同时可能会存在多个使用了 configureBuild Hook
plugin,所以这里取到的 configuredBuild 会是一个数组。然后,再通过 map 方法遍历 configureBuild 数组并调用每一个 configureBuild Hook,将用户的 configbuilds 暴露給它。

const postBuildHooks = toArray(config.configureBuild).map((configureBuild) => configureBuild(config, builds)).filter(Boolean) as PostBuildHook[]

可以看到,这里 vite 只是将 builds 数组暴露给了 configureBuild Hook,我们可以选择性地操作 builds

虽然 configBuild Hook 出现的目的是为了让用户能更多地操作 bundle 的打包过程,但这并不意味着它的优先级(Priority)是最高的。 vite 默认打包生成的 bundle 仍然会优先于它被处理,即默认的 bundle 会被放置到 builds 数组的开始。

const rollup = require('rollup').rollup as typeof Rollup
// 默认打包生成的 bundle
const bundle = rollup({...});builds.unshift({id: "index",bundle
});

到这里 builds 数组就构建好了,接下来就是遍历它,进行 bundle 的写操作(即输出到硬盘上),因为 vite 使用的是 Rollup 完成文件的打包,所以这里调用的是 bundle.write 来将文件输出到硬盘上。

for (const build of builds) {const bundle = await build.bundle;const { output } = await bundle[write ? 'write' : 'generate']({dir: resolvedAssetsPath,format: 'es',sourcemap,entryFileNames: `[name].[hash].js`,chunkFileNames: `[name].[hash].js`,assetFileNames: `[name].[hash].[ext]`,...config.rollupOutputOptions});build.html = await renderIndex(output);build.assets = outputawait postBuildHooks.reduce((queue, hook) => queue.then(() => hook(build as any)),Promise.resolve();)
}

默认情况下,write 是为 true,即会调用 bundle.write,将代码写入到硬盘上,这也是为什么我们的打包后的结果会输出到 dist 目录的原因。在每次遍历 builds 的最后,vite 会调用 postBuildHooks 来使用在开始时调用 configureBuild Hook 返回的函数(通常会是一个 Promise),由于 postBuildHooks 是一个 Promise 数组,所以这里使用了 reduce 方法来保证 Hook 的调用顺序。

并且,我想大家应该也注意到,当我们设置 writefalse 的时候,此时调用的是 bundle.generate,输出的只是 codesourcemap,如果这样,我们就需要通过 configureBuild Hook 进行后续的文件写的操作!而且,我们还可以在 Hook 中进行一些代码转化操作,例如使用 bable-coretransform(),这样一来就很轻松地实现了对 ie11 的支持。

写在最后

正如 configureBuild Hook 的介绍一样,它的出现会给 vite 带来更多强大的插件。例如,我们可以在 configureBuild Hook 中修改 index.html 中的 <script/>,加载 polyfill.io 提供的垫片文件地址,从而实现对旧浏览器的兼容,这也是 aleclarson 大佬的 vite-plugin-legacy 的实现思路。最后,如果文中存在表达错误或不当的地方,欢迎各位同学提 Issue。

❤️ 爱心三连击

通过阅读,如果你觉得有收获的话,可以爱心三连击!!!

vite 不支持 ie 11?configureBuild Hook 帮你定制 bundle 打包过程相关推荐

  1. linux下安装或升级GCC 4.8以上版本(包括),以支持C++11

    本文转载自:http://www.cnblogs.com/lizhenghn/p/3550996.html C++11标准在2011年8月份获得一致通过,这是自1998年后C++语言第一次大修订,对C ...

  2. Vue 3 不再支持 IE 11!

    4 月 3 日,Vue 作者尤雨溪宣布:Vue 3 将不会支持 IE11. 之所以不支持 IE 11,主要原因还是因为 IE 已逐渐边缘化.据 StatCounter 数据显示,在全球市场中,IE 的 ...

  3. 十分钟了解vite如何支持react

    丁楠:  微医前端技术部医疗支撑组  专业标题党,人菜瘾大的刀斯林 前言 vite 是基于浏览器支持 ESM 模块,用以解决大型应用本地开发环境打包.热更新时间久的一套解决方案,目前已支持vue.re ...

  4. android11有哪种手机,支持安卓11系统的机型有哪些

    安卓11系统可以在什么手机上使用?支持Android 11升级的具体机型有哪些?美国当地时间周二,谷歌正式发布了最新版本的移动操作系统 Android 11,并将源代码推给了 Android 开放源代 ...

  5. PyTorch 1.7发布,支持CUDA 11、Windows分布式训练

    机器之心报道 参与:魔王.小舟 昨日,PyTorch 团队发布 PyTorch 1.7 版本.该版本增添了很多新特性,如支持 CUDA 11.Windows 分布式训练.增加了支持快速傅里叶变换(FF ...

  6. PyTorch 1.7发布:支持CUDA 11、Windows分布式训练

    木易 发自 凹非寺  量子位 报道 | 公众号 QbitAI 自从7月份CUDA 11发布以来,就陆陆续续听到了网友类似的吐槽: 这正说着,10月27日,PyTorch团队发布了PyTorch 1.7 ...

  7. VC6生成随机浮点数、C++11的random头文件以及Dev C++支持C++11

    生成随机数: c语言是用 stdlib.h 里面的 rand()函数: c++是 在 #include 里面的 std::random_device 类,该类重载了函数符号():根据资料random是 ...

  8. Electra 支持 iOS 11.4.1 正式版越狱

    在 2018 年 Electra 最新能支持到 11.3.1 越狱,很长的一段时间 11.4 只能支持 Beta 版本,临近春节给了我们一个大礼物,终于支持 iOS 11.4-11.4.1,目前 iO ...

  9. linux之让终端支持C++11/14编译cpp文件

    1  问题 我们的项目很多智能指针,但是我linux的终端肯定不支持C++11/14, 我们平时都是用的下面的命令编译c++文件 g++ -g file.cpp -o file r 如果是用c++11 ...

最新文章

  1. android c聊天功能,Android实现简单C/S聊天室应用
  2. 重装windows2003遇到的老问题:0X0000007B和显卡驱动安装不上。
  3. javascript 内部函数的定义及调用
  4. 归并排序之——二路归并(c/c++)
  5. 一篇来自前端同学对后端接口的吐槽:痛!
  6. scala入门示例helloworld及idea中集成Scala库
  7. 用inno做setup遇到的一些问题及解决方法
  8. Visual Studio—— IntelliSense: #error 指令: Please use the /MD switch for _AFXDLL builds
  9. 你还记得珠算的口诀吗?
  10. 数据结构与算法:十大排序算法之插入排序
  11. VALSE学习(一):high-resolution representation learning-高分辨率表示学习-姿态估计
  12. Linux/Unix/Mac OS下的远程访问和文件共享方式
  13. PMP助力!让你成功转型项目管理
  14. android打印机字体大小,打印自定义文档  |  Android 开发者  |  Android Developers
  15. 散列表(线性探测法二次探测法)
  16. 《实变函数简明教程》,第三章:可测函数,连续函数复合可测函数是可测函数
  17. 那些花儿那片笑声让我想起我的那些花儿在我生命每个角落静静为我开着我曾...
  18. 芒果超媒前三季营收102亿:同比降12% 互联网广告收入降26%
  19. python涨工资问题_7-45 jmu-python-涨工资 (10 分)
  20. 数据分析--Python连接阿里云数据库

热门文章

  1. 终于把python的所有库整理完毕了,现在一篇python库的字典诞生了
  2. 开关量模块在报警系统中的应用
  3. android qq隐藏功能,90﹪的人都不知道--手机QQ这些隐藏的功能!
  4. PS如何批量处理图片尺寸大小?免费哟
  5. PTA 数据结构与算法 7-29 修理牧场
  6. 移动常见问题--H5标签之浏览器兼容性、JS之浏览器兼容性、CSS3之浏览器兼容性、移动端动画、click300ms延迟、单行和多行文字溢出省略、水平居中和垂直居中
  7. Python爬虫-爬取手机应用市场中APP下载量
  8. python-正负数交叉排序
  9. 学科实践活动感悟50字_社会实践活动的自我评价50字
  10. 大屏监控 Metabase 集成到 Java 项目