当前位置:网站首页>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.
- 内部使用的是
koa
Framework 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')
import
Differences 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.vue
Suffixed 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.vue
suffixed 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
全文终…
边栏推荐
- Tencent Cloud [Hiflow] New Era Automation Tool
- Principle and Technology of Virtual Memory
- [Solved] Unity Coroutine coroutine is not executed effectively
- MRTK3开发Hololens应用-手势拖拽、旋转 、缩放物体实现
- 论治理与创新,2022 开放原子全球开源峰会 OpenAnolis 分论坛圆满落幕
- Summary of domestic environments supported by SuperMap
- 2022.8.4-----leetcode.1403
- 龙蜥社区第二届理事大会圆满召开!理事换届选举、4 位特约顾问加入
- ASP.NET应用程序--Hello World
- High Item 02 Information System Project Management Fundamentals
猜你喜欢
Tencent Cloud [Hiflow] New Era Automation Tool
结构体初解
你要的七夕文案,已为您整理好!
【软件测试】自动化测试之unittest框架
mysql can't Execute, please solve it
运维监控系统之Open-Falcon
QT MV\MVC structure
冒泡排序与快速排序
On governance and innovation, the 2022 OpenAtom Global Open Source Summit OpenAnolis sub-forum came to a successful conclusion
[Solved] Unity Coroutine coroutine is not executed effectively
随机推荐
Dameng 8 database export and import
sql server 安装提示用户名不存在
【已解决】Unity Coroutinue 协程未有效执行的问题
ASP.NET应用程序--Hello World
In 2022, you still can't "low code"?Data science can also play with Low-Code!
tree table lookup
惨遭打脸:字节某部门竟有这么多测试员
torch.roll()
Summary of domestic environments supported by SuperMap
.NET Application -- Helloworld (C#)
Web3.0 Dapps——通往未来金融世界的道路
21 Days Learning Challenge (2) Use of Graphical Device Trees
IJCAI2022 | DictBert: Pre-trained Language Models with Contrastive Learning for Dictionary Description Knowledge Augmentation
How Jin Cang database correctness verification platform installation file
How to sort multiple fields and multiple values in sql statement
为什么pca分量没有关联
Dynamic management of massive service instances
undo problem
Cybersecurity and the Metaverse: Identifying Weak Links
Step by step how to perform data risk assessment