Code前端首页关于Code前端联系我们

您如何看待Web开发工具Vite?

terry 2年前 (2023-09-08) 阅读数 136 #Vue

vite startlink

作业分析

这部分代码在src/node/cli.ts中。使用cac,它用于从命令行CLI构建script脚本。
vite主要构建了四个script命令:dev、build、preview和optimize。

服务器

服务器模块用于开发模式。这部分代码位于src/node/server/index.ts,主要暴露了一个createServer方法。
vite 启动服务器。当浏览器读取HTML文件时,在执行导入时会将main.vue模块中的请求发送到服务器。在服务器上创建自定义文件后,下面分析如何实现热更新。

优化

优化指的是依赖项的预编译。在启动用户开发服务器之前,vite首先使用esbuild
构建检测到的依赖关系。

vite一直主张不捆绑,但为什么还在开始之前构建依赖关系呢?

例如,如果项目中使用了import { debounce } from 'lodash'这样的函数,并且debounce函数的模块依赖于许多其他函数,则形成依赖图。如果项目中没有提前创建依赖项。在构建过程中,实际开发过程中可以发起多个请求。

const listen = httpServer.listen.bind(httpServer);
httpServer.listen = (async (port: number, ...args: any[]) => {
  try {
    await container.buildStart({});
    // 这里会进行依赖的预构建
    await runOptimize();
  } catch (e) {
    httpServer.emit("error", e);
    return;
  }
  return listen(port, ...args);
}) as any;
 

runOptimize 将方法 optimizeDepsDepOptimizationMetadata 导入到 src/node/optimizer/index.ts 中。特别是,它没有介绍如何使用 esbuild 将依赖项预先打包到单文件包中。
浏览器依赖预编译后,在请求相关模块时会返回预构建的模块。这样,当浏览器请求lodash-es中的debounce模块时,可以保证只出现一个界面。去问。

构建

该组件位于src/node/build.ts,vite采用rollup封装,并提供插件机制,兼容Rollup格式。所谓插件就是外部提供的一些时序钩子,以及一些允许用户编写配置代码来干预rollup操作的各种时序的工具和方法。

越南工作原理

模块化

什么是前端模块化?简单来说,就是一部分。模块是实现特定功能的文件(js)。根据模块化机制,在需要时加载相应的模块。

js中有四种模块化规范:AMD、CMD、Commonjs和EsModule。目前使用最多的是 Commonjs 和 EsModule。

常见的J

function a() {}
module.exports = { a };
/*引入*/
const a = require("a");
 

EsModule

export function a() {}
const { a } from '..xxx'
 

commonJs 被调用时执行。输出值是前一个副本,但它有缓存。当第一次加载时,整个文件被完全执行并输出一个对象。下次加载该文件时,该文件将立即被清除。记忆中的价值。 esModule 在编译时加载,输出只是对模块值的引用。

目前大多数浏览器都支持export import来导入导出模块。在script标签中设置type="module",然后使用模块内容。这样就消除了打包步骤,并且您想要使用的所有资源都可以直接导入到浏览器中。使用浏览器解析导入,
在服务器端根据请求进行编译并返回。

拆除包装步骤

打包的概念是开发者使用工具将应用程序中的几个模块集合在一起形成一个bundle
,并按照一定的规则读取模块代码——以便可以在支持此功能的浏览器中使用不支持模块化。虽然代码中有延迟加载路由等方法,但这并不意味着有延迟构建。仍然需要预先构建所有使用的模块,并使用粘合代码来组装每个模块。例如,Webpack使用文件夹来存储模块ID和路径,并使用__webpack_require__方法获取模块导出。随着项目越来越大,需要构建的文件也会越来越大。启动和HMR也越来越慢。而Vite利用原生支持模块化导入的特性,省略了模块的组装,因此不需要bundle。这两种方法可以用两张图来形象地描述。
打包打包

esmoduleesmodule

vite模块分析

浏览器使用es模块通过http请求获取模块,因此vite提供了一个Web服务器来代理这些模块。通过劫持请求路径,检索源内容并将其发送回浏览器。

对比项目下的index.html和开发环境下的html源文件,发现script标签中的内容发生了变化,从

import { createApp } from "vue";
import App from "/App.vue";
createApp(App).mount("#app");
 

变成了

import { createApp } from "/node_modules/.vite/vue.js?v=df64d8b4";
import App from "/App.vue";

createApp(App).mount("#app");
 
  • http请求获取的body内容,
  • 使用es-module-lexer进行词法分析,解析源码,获取导入的内容。
  • 如果模块不包含exports关键字,则被视为commonjs模块。如果它包含exports关键字,我们认为它是一个esmodule。我们进一步分析进口-进口关系。如果导入的模块以.开头,则被视为es模块。真正的依赖项,如果绝对导入,则被视为 npm 模块。

如果我们在模块中编写代码,浏览器的esm不可能在导入的模块中存活

import vue from "vue";
 

由于vue模块安装在node_modules中,所以我们过去一直使用webpack。当 webpack 遇到上面的代码时,它会帮助我们做以下事情:获取这段代码的内容并解析成 AST,遍历 AST 并将包放入 import 语句中。使用增强解析来获取包的实际地址进行打包,但是浏览器中的ESM无法直接访问项目下的node_modules,所以vite处理了所有的导入,

热替换

模块热替换是指更改代码,使其在不刷新页面的情况下生效。 vite通过websocket建立服务器和浏览器之间的通信。热更新通常需要四个部分:

  1. 首先,Web框架必须支持重新渲染/重新加载模块
  2. 通过 watcher 收听文件更改
  3. 通过服务器编译源码并将新模块内容推送到客户端
  4. 客户端收到新的模块内容并执行重新渲染/重新加载

在服务器端,watcher 监控页面变化,并根据文件类型判断是 js reload、Vue reload 还是 css reload。解析器检索当前文件等的模板,并将其与缓存中的最后解析结果进行比较。

vue文件修改时会触发handleVueReload方法

//src/node/server/serverPluginVue.ts
watcher.on("change", (file) => {
  if (file.endsWith(".vue")) {
    handleVueReload(file);
  }
});
 

首先使用parseSFC库编译单个vue文件,并从缓存中读取之前的组件缓存。如果没有,则意味着该项目尚未渲染,无需执行任何操作。

  • 如果我们前后两次显示同一个item时,script或script安装不一致,我们需要使用vue-reload来重新加载整个item。
  • 如果
  • 前后的模板不一致,则会发送vue渲染器消息。只需使用输入模板提交请求即可。
  • 样式的差异通过 style-update 样式标签更新

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门