当前位置:网站首页>Dive into how it works together by simulating Vite
Dive into how it works together by simulating Vite
2022-08-05 03:24:00 【too lazy to fight pigs】
Vite实现原理(静态web服务器)
vite的核心功能
- 静态web服务器
- 启动Vite的时候,Will write the current directory to the root directory of the static file server.
- The static file server intercepts some requests,For example a single-file component,Intercept the request for just-in-time compilation and return the result.and style precompiled module code.
- 内部使用的是
koaFramework to start a static file server
- 编译单文件组件
- 拦截浏览器不识别的模块并处理
- HMR
- 通过web socketRealize hot module replacement.
模拟viteImplement a server that enables static filesCLI
vite-cli 模拟项目
Let's open it firstviteThe front-end of the project requests the path and content of the resource and the difference between the content and the project directory file:
浏览器请求:
第2个是client是HMR所用到的web socket 的client,Here we only simulate and implement the basic core functions,此处忽略HMR相关的内容.
see the thirdmain.js
// main.js
import {
createApp } from '/node_modules/.vite/deps/vue.js?v=b039f9b3'
import App from '/src/App.vue'
createApp(App).mount('#app')
You can see that the path is different from our source code.The contents of our handwritten source code are as follows:
import {
createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
importDifferences in resource paths imported later:
如果是第三方模块:The request path is converted to /node_modules/Begins with a relative path to the real module file in the current project's third-party resource.
Self-written modules:请求路径./会转化为/src/开头
Look at the follow-up request.vueSuffixed single-file component resource:
// 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...
We wrote it ourselvesApp.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: center; color: #2c3e50; margin-top: 60px; } </style>
The difference is that the server [email protected]/compiler-sfc编译的内容,The internal custom component access path was modified to /src/App.vue?vue&type=style&index=0&lang.css,And the returned content is added last//# sourceMappingURL=data:application/json;base64,eyJ2Z...的sourceMap项目内容.
后面的HelloWorld.vue也是同样情况.
请求的HelloWorld.vue内容:
import {
createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/components/HelloWorld.vue");import {
reactive } from '/node_modules/.vite/deps/vue.js?v=b039f9b3'
const _sfc_main = {
__name: 'HelloWorld',
props: {
msg: String
},
setup(__props, {
expose }) {
expose();
const state = reactive({
count: 0 })
const __returned__ = {
state, reactive }
Object.defineProperty(__returned__, '__isScriptSetup', {
enumerable: false, value: true })
return __returned__
}
}
import {
toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "/node_modules/.vite/deps/vue.js?v=b039f9b3"
const _withScopeId = n => (_pushScopeId("data-v-469af010"),n=n(),_popScopeId(),n)
const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("p", null, [
/*#__PURE__*/_createElementVNode("a", {
href: "https://vitejs.dev/guide/features.html",
target: "_blank"
}, " Vite Documentation "),
/*#__PURE__*/_createTextVNode(" | "),
/*#__PURE__*/_createElementVNode("a", {
href: "https://v3.vuejs.org/",
target: "_blank"
}, "Vue 3 Documentation")
], -1 /* HOISTED */))
const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("p", null, [
/*#__PURE__*/_createTextVNode(" Edit "),
/*#__PURE__*/_createElementVNode("code", null, "components/HelloWorld.vue"),
/*#__PURE__*/_createTextVNode(" to test hot module replacement. ")
], -1 /* HOISTED */))
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("h1", null, _toDisplayString($props.msg), 1 /* TEXT */),
_hoisted_1,
_createElementVNode("button", {
type: "button",
onClick: _cache[0] || (_cache[0] = $event => ($setup.state.count++))
}, " count is: " + _toDisplayString($setup.state.count), 1 /* TEXT */),
_hoisted_2
], 64 /* STABLE_FRAGMENT */))
}
import "/src/components/HelloWorld.vue?vue&type=style&index=0&scoped=true&lang.css"
_sfc_main.__hmrId = "469af010"
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],['__scopeId',"data-v-469af010"],['__file',"/Users/huiquandeng/projects/lg-fed-lp/my-module/vite-cli-demo/vite-demo/src/components/HelloWorld.vue"]])
//# sourceMappingURL=data:application/json;base64,eyJ2Z...
We handcraftedHelloWorld.vue,内容如下:
<template>
<h1>{
{ msg }}</h1>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
Vite Documentation
</a>
|
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
</p>
<button type="button" @click="state.count++">
count is: {
{ state.count }}
</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<script setup> import {
defineProps, reactive } from 'vue' defineProps({
msg: String }) const state = reactive({
count: 0 }) </script>
<style scoped> a {
color: #42b983; } </style>
The paths are also converted into /src/components/HelloWorld.vue?vue&type=style&index=0&scoped=true&lang.css
So next to the above two.vuesuffixed when the file component will be requested again,And with some parameters as follows:vue&type=style&index=0&scoped=true&lang.css,解析Query string parameters值如下:
vue:
type: style
index: 0
scoped: true
lang.css:
vue Indicates the frame type of the template used by the current single-file componenttype Indicates the resource type in the current balloon template,Correspondence is required when processing this single-file componentvue的compiler进行编译,The types obtained aretemplate/style/script等.index This is that different types of resources may exist in multiple parts,index是数组的索引scoped Indicates whether the style files in the current component file are of local scope or global scopelang.css Indicates the style precompiled language type used by the current style.如果是scss/less/stylus/postcssetc. require corresponding pre-compilation processing.
模拟实现vite-cli
根据以上分析,我们模拟vite-cliThe steps can be roughly divided into the following steps:
- 使用koaThe framework creates a static file server.
- Use middleware to modify the path of third-party modules
- 加载第三方模块
- 编译单文件组件
- Request paths for handling other types of static resource files
- To optimize the speed faster,You also need to add a corresponding cache for each conversion process,To avoid converting the same files with the same steps.
实现代码
首先创建一个目录,使用npm init -y进行初始化后,package.json中配置CLIRequired option for the projectbin, 如下:{“bin”: "index.js}"
So the entry file of our project isindex.js,内容如下:
// index.js
// This guy is so lazy,After reading the source code, I am too lazy to implement it
// 源码vite中还实现了pluginThe framework used by the form configuration
全文终…
边栏推荐
- Principle and Technology of Virtual Memory
- 冒泡排序与快速排序
- 高项 02 信息系统项目管理基础
- MRTK3开发Hololens应用-手势拖拽、旋转 、缩放物体实现
- Syntax basics (variables, input and output, expressions and sequential statement completion)
- 2022 High-level installation, maintenance, and removal of exam questions mock exam question bank and online mock exam
- Everyone in China said data, you need to focus on core characteristic is what?
- sql server 安装提示用户名不存在
- 通过模拟Vite一起深入其工作原理
- private package
猜你喜欢

2022-08-04T17:50:58.296+0800 ERROR Announcer-3 io.airlift.discovery.client.Announcer appears after successful startup of presto

Principle and Technology of Virtual Memory

Kubernetes 网络入门

The second council meeting of the Dragon Lizard Community was successfully held!Director general election, 4 special consultants joined

Question about #sql shell#, how to solve it?

.NET应用程序--Helloworld(C#)

结构体初解

大像素全景制作完成后,推广方式有哪些?

Web3.0 Dapps——通往未来金融世界的道路

基于生长的棋盘格角点检测方法
随机推荐
STM32 uses stm32cubemx LL library series tutorial
Leading the highland of digital medicine, Zhongshan Hospital explores to create a "new paradigm" for future hospitals
YYGH-13-客服中心
运维监控系统之Open-Falcon
How to transfer a single node of Youxuan database to a cluster
通过模拟Vite一起深入其工作原理
J9 Digital Currency: What is the creator economy of web3?
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)
Use SuperMap iDesktopX data migration tool to migrate map documents and symbols
语法基础(变量、输入输出、表达式与顺序语句)
Ffmpeg - sources analysis
21 Days Learning Challenge (2) Use of Graphical Device Trees
Confessing the era of digital transformation, Speed Cloud engraves a new starting point for value
undo problem
Queue Topic: Recent Requests
The second council meeting of the Dragon Lizard Community was successfully held!Director general election, 4 special consultants joined
In 2022, you still can't "low code"?Data science can also play with Low-Code!
Beyond YOLO5-Face | YOLO-FaceV2 officially open source Trick+ academic point full
Web3.0 Dapps——通往未来金融世界的道路
为什么pca分量没有关联