范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Vite是如何使用Rollup进行构建的

  我们都知道,Vite 在生产环境中,会使用 Rollup 进行构建,那么 Vite 是如何做到的呢?本文将讲述,从执行  vite build   到输出构建产物,这期间到底发生了什么?Vite 的 build 命令
  我们直接来看 build 命令的源码 // build cli   .command("build [root]", "build for production")   .option("--target ", `[string] transpile target (default: "modules")`)   .option("--outDir ", `[string] output directory (default: dist)`)   .option("-w, --watch", `[boolean] rebuilds when modules have changed on disk`)   .action(async (root: string, options: BuildOptions & GlobalCLIOptions) => {     // build 命令会执行的内容        }) 复制代码cli.command   定义了 build 命令options   函数定义了一些 build 命令的参数,声明的 option 参数,会出现在函数参数 options 中
  我们来看看 build   命令实际执行的内容:const { build } = await import("./build") // 处理 options 参数 const buildOptions: BuildOptions = cleanOptions(options)  try {     await build({         root,         base: options.base,         mode: options.mode,         configFile: options.config,         logLevel: options.logLevel,         clearScreen: options.clearScreen,         optimizeDeps: { force: options.force },         build: buildOptions,     }) } catch (e) {     createLogger(options.logLevel).error(         colors.red(`error during build: ${e.stack}`),         { error: e },     )     process.exit(1) } finally {     stopProfiler((message) => createLogger(options.logLevel).info(message)) } 复制代码
  因此,build   命令实际上就是执行 build   函数
  build   函数如下:let parallelCallCounts = 0 const parallelBuilds: RollupBuild[] = []  export async function build(   inlineConfig: InlineConfig = {}, ): Promise {   parallelCallCounts++   try {     return await doBuild(inlineConfig)   } finally {     parallelCallCounts--     if (parallelCallCounts <= 0) {       await Promise.all(parallelBuilds.map((bundle) => bundle.close()))       parallelBuilds.length = 0     }   } } 复制代码
  实际上这里调用了 doBuild   函数。doBuild   函数中则是真正的执行构建了。
  这里的并行处理的代码,是历史遗留逻辑,如今已经是没有用了。这部分在该 pull request 已经被删除,但截至发文该改动未被合入到 master  执行构建
  在 doBuild   函数中,Vite 利用 Rollup 的 JS API 执行构建。
  Rollup JS API 的使用分为两部分:打包阶段:调用 rollup   函数,传入 input 配置,会得到 bundle   对象,此时不会生成代码。生成阶段:有以下两种方式调用 bundle.generate  ,传入 output 配置,得到构建后的代码。调用 bundle.write  ,传入 output 配置,根据 output 配置,将构建后代码写入到磁盘。async function build() {   // create a bundle   let  bundle = await rollup(inputOptions);    // 从 bundle 生成代码并返回,拿到的是字符串,可以进行进一步的处理   const { output } = await bundle.generate(outputOptions);   // 或直接从 bundle 生成代码并写入到磁盘,直接生成文件   await bundle.write(outputOptions)     // closes the bundle   await bundle.close(); } 复制代码
  同样的,Vite 通过 Rollup JS API 生成代码,需要生成 input 和 output 配置,总的流程如下:
  标准化 Vite 配置async function doBuild(   inlineConfig: InlineConfig = {}, ): Promise {     // 生成一份标准化后的配置     const config = await resolveConfig(         inlineConfig,         "build",         "production",         "production",     )     // 省略其他逻辑 } 复制代码
  doBuild   的第一步,就是标准化 Vite 的配置,这里用的是 resolveConfig   函数,它会读取项目目录的 Vite 配置文件(如 vite.config.ts  ),并跟 Vite 的一些内容配置进行合并,最终返回。
  它的行为与 Vite dev   完全一致。如果对 Vite 的配置解析感兴趣,可以参考我写过的文章《五千字剖析 vite 是如何对配置文件进行解析的》,在该文章中,详细叙述过这个完成的流程。其主要有以下几步:读取配置文件,为了兼容 TS 格式的配置文件,Vite 还会对配置文件进行编译再读取处理插件,对插件进行排序,加入 Vite 内置插件等读取环境变量文件,读取 .env   等文件Rollup input 配置
  Vite 生成的 rollup 配置如下:const rollupOptions: RollupOptions = {     context: "globalThis",     // vite 配置文件的 build.rollupOptions 对象     ...options.rollupOptions,     input,     plugins,     external, } 复制代码
  我们用 Vite 仓库中自带的示例项目打个断点看看:
  可以看到,Rollup 配置中主要有这么几个配置:input  :打包的入口,从配置中计算出来,默认是 index.html  ,因此我们配置中即使没有填入口,Vite 也能正确的执行构建const input =      //	如果设置了 build.lib 对象,则对 build.lib 进行处理,需要支持多入口构建     libOptions     ? options.rollupOptions?.input ||           (typeof libOptions.entry === "string"            ? resolve(libOptions.entry)            : Array.isArray(libOptions.entry)            ? libOptions.entry.map(resolve)            : Object.fromEntries(               Object.entries(libOptions.entry).map(([alias, file]) => [                   alias,                   resolve(file),               ]),           )) 	// 没有设置 build.lib     : typeof options.ssr === "string"         ? resolve(options.ssr) 		// 什么也不填,就会走到这里,默认入口是当前目录的 index.html         : options.rollupOptions?.input || resolve("index.html") 复制代码plugin  :打包用到的插件
  plugin   中,加入了很多 Vite 的内置插件。Vite 的很多开箱即用的能力,都是由这些插件提供的(Rollup 本身没有内置这些能力),例如:alias 别名CSS、less、sass 等处理CommonJs 处理(Rollup 本身不能处理,是通过插件支持 CommonJs 的)HTML 入口的处理……
  由于篇幅优先,这些插件就不一一介绍了。
  在 vite build 与 vite dev 两种模式下,使用的插件都是相同的,Vite 在开发模式下,模仿 Rollup 仿造出了一套拥有相同的 API 的插件架构,使得插件在两种模式下都能正常使用,保证了两种模式下 Vite 有相同的行为。更多细节可以查看文章《Vite 是如何兼容 Rollup 插件生态的》
  Rollup output 配置
  Rollup 输出产物的代码如下:const generate = (output: OutputOptions = {}) => {   // 调用  bundle.write 或 bundle.generate   return bundle[options.write ? "write" : "generate"](output) }  if (options.write) {   // 如果需要写入磁盘,就先准备输出目录,确保目录存在,并且清空目录   prepareOutDir(outDirs, options.emptyOutDir, config) }  const res = [] // normalizedOutputs 为多个输出配置,因为可能一次构建,会输出多份代码 // 常见于构建 lib,需要分别输出 umd、esm 等多种格式的产物 for (const output of normalizedOutputs) {   res.push(await generate(output)) } return Array.isArray(outputs) ? res : res[0] 复制代码
  同样的,我们还是打个断点看看:
  output 参数中,定义了产物输出目录、产物 js 版本、名称格式等,因此,我们可以看到有以下的构建产物。
  output   配置的生成// 标准化 output 配置,从 vite 配置中生成 const outputs = resolveBuildOutputs(     options.rollupOptions?.output,     libOptions,     config.logger, ) const normalizedOutputs: OutputOptions[] = []  if (Array.isArray(outputs)) {   // 处理多入口的情况   for (const resolvedOutput of outputs) {     normalizedOutputs.push(buildOutputOptions(resolvedOutput))   } } else {   normalizedOutputs.push(buildOutputOptions(outputs)) } 复制代码
  buildOutputOptions   函数如下,主要是包装完整的 output 构建配置(大概看一下就行了):const buildOutputOptions = (output: OutputOptions = {}): OutputOptions => {     const ssrNodeBuild = ssr && config.ssr.target === "node"     const ssrWorkerBuild = ssr && config.ssr.target === "webworker"     const cjsSsrBuild = ssr && config.ssr.format === "cjs"      const format = output.format || (cjsSsrBuild ? "cjs" : "es")     const jsExt = ssrNodeBuild || libOptions         ? resolveOutputJsExtension(format, getPkgJson(config.root)?.type)         : "js"     return {         dir: outDir,         format,         exports: cjsSsrBuild ? "named" : "auto",         sourcemap: options.sourcemap,         name: libOptions ? libOptions.name : undefined,         // vite 默认生成 es2015,因此默认是不支持传统老的浏览器         generatedCode: "es2015",         entryFileNames: ssr         ? `[name].${jsExt}`         : libOptions         ? ({ name }) =>         resolveLibFilename(libOptions, format, name, config.root, jsExt)         : path.posix.join(options.assetsDir, `[name]-[hash].${jsExt}`),         chunkFileNames: libOptions             ? `[name]-[hash].${jsExt}`             : path.posix.join(options.assetsDir, `[name]-[hash].${jsExt}`),         assetFileNames: libOptions             ? `[name].[ext]`             : path.posix.join(options.assetsDir, `[name]-[hash].[ext]`),         inlineDynamicImports:             output.format === "umd" ||             output.format === "iife" ||             (ssrWorkerBuild &&              (typeof input === "string" || Object.keys(input).length === 1)),         ...output,     } } 复制代码
  至此,整个完整的 Rollup 配置就出来了。总结
  Vite build 的代码量其实非常的少,因为在 build 阶段,Vite 是利用 Rollup 去完成构建,整个过程只需要调用 Rollup 提供的 JS API 即可,整个过程中,Vite 的工作只是在做配置的转换,把 Vite 的配置转换成 Rollup 的 input 和 output 配置。
  Vite 通过在 dev   模式时,模拟出一套与 Rollup 相同的插件架构,通过 dev   和 build   模式使用同一套插件,从而使两个模式下有相同的构建行为。关联阅读《Vite 是如何兼容 Rollup 插件生态的》《五千字剖析 vite 是如何对配置文件进行解析的》

平民百姓,别信理财的鬼话连篇机构富人让你理财多半是庞氏骗局。你要这么想,你好不容易有点闲钱,想想你从1万到100万的过程多么艰辛漫长?你就那么容易把自己的血汗钱拱手让人基金去练刀?让机构去理财?到时,钱也没了经济学家称消费不是刺激出来的解决切身问题,老百姓才敢消费近日,国民经济研究所副所长王小鲁,在某档节目采访中,直言消费不是刺激出来的。王小鲁认为消费是人的自然需要,衣食住行丰富文化生活等,都不是靠刺激消费才出现的要把老百姓基础的住房医疗养我宁愿被割韭菜Sb一个6000你只能买个128的水果,不送充电器丑陋的刘海辣鸡的续航龟速的充电差劲的信号(这就是用户体验)。水果体验好,水果做坨屎你们都舔。水果粉审美不及格,一个曾经工业设计第一钱多了不等于幸福广厦千间,夜眠仅需八尺良田万顷,日食不过三餐。昨日,访老友。友说我现在非常快乐,我对现在拥有的一切感到非常满意。够了。够了,两个字,说明他很清醒很明智。钱多不等于幸福。马修说,钱对晨跑有悟惜时,爱时,才是时间邹学勇。2022。9。30晨跑起来,一路上自燃的力量,被周围风景笼罩,大自然的气息渗透在心里,全身被心灵的力量灌满,一路上的样子在读有字之书,听有理之语,人生的乐趣就是行走,惜福当雍正后代的高知分子与农妇厮守73年,断了三代单传的皇族血脉一份感情重要的从来都不是物质的给予,而是精心准备的惊喜,是被人挂念的关心,是寸步不离的守候,是用尽一生陪伴。人生之幸,无非两种,一是饱餐二是被爱。在这个快餐年代,爱意随风四起,真诚十月你好愿你向内而行,学会哄自己开心一念花辞树,一念秋风凉。时序更替,转眼间已是深秋。回首过去的日子,向外追求,烦恼重重,倍感压力与焦虑。其实人生在世,只有向内而行,卸下外界的负累,未来的路才会快乐而轻松。正如佛家所诗一首五星红旗英雄与先烈的热血浸染的旗帜啊被五颗闪闪发光的星星照耀得熠熠生辉成为永不倒下的精神哪怕被子弹洞穿哪怕被炮火撕裂依然猎猎飘扬依然叱咤风云一面旗帜升起从南昌城头从井冈山上从延安从西柏坡到Win11如何设置图片密码?6步就能给你的私密图片加把锁在Win系统中有着多种不同的登录密码种类,这么多的登录密码里,我们最常用的就是密码登录,那么在Win11系统中,如何设置图片密码来进行登录呢?想知道的小伙伴,可以跟着电脑百科林老师不升反降?难怪iphone14的销量这么差,双频定位没有了很多年一年中换新机的冲动基本都是在iphone发布新机之后,但是今年,iphone14系列一发布之后,可谓是让人大跌眼镜,有一点盛极必衰的势态了。首先来说,iphone14系列这次宏碁最便宜的i512500H满血3060一线品牌游戏本有啥优缺点?今年的宏碁性价比非常高,尤其是暗影骑士擎系列,可以说是同配置一线品牌里性价比最高的。本期我们看一台目前性价比最高的暗影骑士擎游戏本,配置是i512500H满血3060,目前百亿补贴
儿童感染奥密克戎的症状是什么?小舒答疑为固定栏目,每天推送,记得收藏哟。也欢迎大家在本篇文章下面留言,写下你在育儿道路上的疑问QAQ儿童感染奥密克戎的症状是什么?A虽然儿童与成年人一样容易感染新冠病毒,但儿童患海港主力回归也难阻泰山?卫冕冠军取胜概率直线飙升已超6成北京时间12月23日,中超第32轮的焦点大战中,上海海港在晋江赛区迎战山东泰山。虽然赛前有消息称,海港的多名主力回归,不过从赛前的权威数据分析来看,泰山的取胜可能性已经从57。17演员罗海琼37岁嫁豪门,42岁高龄生二胎,如今两个女儿成她骄傲2010年,费麒包下当地最豪华五星级酒店,准备给罗海琼一场难忘世纪婚礼。仪式进行时,他突然宣布我自愿将公司价值3823万的股份,全部无条件赠给妻子。此话一出,在场宾客哗然一片,之后股市晚评历史总是惊人的相似,变盘信号出现!经过这一轮大跌,中证1000指数今天在KDJ钝化后拐头向上之际,收出了十字星,这是有变盘的希望了,历史不会一样,但会惊人的相似在这个位置能不能构筑大双底,值得期待!当然,下周能够收化学ampampquot断裂点ampampquot让新型塑料在几天到两个月内完成生物降解塑料是我们这个时代最紧迫的环境问题之一。由于它的多功能性强度和对水和热的抵抗力,它出现在数量惊人的产品中,被使用的时候是表现通常很好,但是,在产品的使用寿命结束后,这些优点就变成了腊月到了,提醒老人少吃豆腐和梨,多吃4样,补心养阳平安过冬马上就要进入腊月了,气温会越来越低,此时人体的抵抗力不强,很容易引发季节性疾病,因此,人们越来越注重身体健康。目前全民都想尽各种办法来提高自身免疫力和身体素质,不给外邪可趁之机!而阿根廷的真正英雄战术大师斯卡洛尼当所有的头条新闻和聚光灯都在梅西身上时,有一个人绝不能被忽略,他就是儒雅少帅斯卡洛尼。本届世界杯最年轻的主教练从去年至今,阿根廷夺得美洲杯欧美杯世界杯,梅西结束了四亚王的尴尬,阿根健康消费新态度,益生菌为健康加码!如今,随着生活水平提高,我们吃的明显变好了。饮食逐渐以动物性食物高糖高脂加工食物为主的西方饮食模式转变,各种添加剂的使用和毒素的不断富集,再加上缺乏运动和不良习惯的产生,我们的身体钱学森再次预言成真,支撑科幻未来的云计算又该如何发展要不怎么说钱学森先生是大预言家呢?先是预言了中国新能源车的发展趋势,再预言了人工智能的发展为人机结合以人为主。三十多年前,先生的系统论里提到相互关联作用和影响的组成部分构成的整体,点亮视界播动未来2022年河北直播电商节拉开帷幕长城网冀云客户端12月23日讯(记者陈兆月)12月23日上午,点亮视界播动未来2022年河北直播电商节在石家庄拉开帷幕。图为2022年河北直播电商节启动仪式现场。2022年河北直播阴阳师新皮肤468?网友以后把收款码放登陆界面吧近日,网易旗下游戏阴阳师的一款游戏皮肤引发了网友们的热议,这款号称臻藏皮肤的价格,完整一套下来需要玩家花费468元,也因此引发了玩家们的不满,有人甚至评论道,以后把收款码放登录界面