通过模拟Vite一起深入其工作原理

本文探讨Vite的核心功能,它作为静态web服务器,处理单文件组件的即时编译和返回。通过模拟vite-cli,创建了一个简单的静态文件服务器,分析了资源请求路径和内容变化,涉及第三方模块处理、编译SFC、样式预编译等关键步骤。最后,给出了模拟实现的基本代码结构。
摘要由CSDN通过智能技术生成

Vite实现原理(静态web服务器)

vite的核心功能

  • 静态web服务器
    • 启动Vite的时候,会将当前目录作文静态文件服务器的根目录。
    • 静态文件服务器会拦截部分请求,例如👇的单文件组件,拦截请求进行即时编译并返回结果。以及样式预编译模块代码。
    • 内部使用的是koa框架来开启静态文件服务器
  • 编译单文件组件
    • 拦截浏览器不识别的模块并处理
  • HMR
    • 通过web socket实现模块热替换。

模拟vite实现一个开启静态文件服务器的CLI

vite-cli 模拟项目

首先我们开一下vite项目的前端请求资源的路径及内容和项目目录文件的差异:
浏览器请求:
在这里插入图片描述
第2个是client是HMR所用到的web socket 的client,这里我们仅模拟实现基本的核心功能,此处忽略HMR相关的内容。
来看第三个main.js

// main.js
import {
    createApp } from '/node_modules/.vite/deps/vue.js?v=b039f9b3'
import App from '/src/App.vue'

createApp(App).mount('#app')

可以看到其中的路径跟我们的源代码是有区别的。我们手写源代码的内容如下:

import {
    createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

import后面导入的资源路径差异:
如果是第三方模块:请求路径会转化为/node_modules/开头真正的模块文件在当前项目的第三方资源相对路径。
自编写的模块:请求路径./会转化为/src/开头

再看后续请求到的.vue后缀的单文件组件资源:

// App.vue
import {
    createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/App.vue");import HelloWorld from '/src/components/HelloWorld.vue'

// This starter template is using Vue 3 experimental <script setup> SFCs
// Check out https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md

const _sfc_main = {
   
  __name: 'App',
  setup(__props, {
     expose }) {
   
  expose();


const __returned__ = {
    HelloWorld }
Object.defineProperty(__returned__, '__isScriptSetup', {
    enumerable: false, value: true })
return __returned__
}

}
import {
    createElementVNode as _createElementVNode, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "/node_modules/.vite/deps/vue.js?v=b039f9b3"

const _hoisted_1 = /*#__PURE__*/_createElementVNode("img", {
   
  alt: "Vue logo",
  src: "/src/assets/logo.png"
}, null, -1 /* HOISTED */)

function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
   
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _hoisted_1,
    _createVNode($setup["HelloWorld"], {
    msg: "Hello Vue 3 + Vite" })
  ], 64 /* STABLE_FRAGMENT */))
}

import "/src/App.vue?vue&type=style&index=0&lang.css"

_sfc_main.__hmrId = "7ba5bd90"
typeof __VUE_HMR_RUNTIME__ !== 'undefined' && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main)
import.meta.hot.accept(({
     default: updated, _rerender_only }) => {
   
  if (_rerender_only) {
   
    __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render)
  } else {
   
    __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated)
  }
})
import _export_sfc from '/@id/plugin-vue:export-helper'
export default /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],['__file',"/Users/huiquandeng/projects/lg-fed-lp/my-module/vite-cli-demo/vite-demo/src/App.vue"]])
//# sourceMappingURL=data:application/json;base64,eyJ2...

我们自编写的App.vue,内容如下:

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <HelloWorld msg="Hello Vue 3 + Vite" />
</template>

<script setup>
import HelloWorld from './components/HelloWorld.vue'

// This starter template is using Vue 3 experimental <script setup> SFCs
// Check out https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
</script>

<style>
#app {
     
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值