当前位置:网站首页>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
全文终…
边栏推荐
猜你喜欢

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

The usage of try...catch and finally in js

On governance and innovation, the 2022 OpenAtom Global Open Source Summit OpenAnolis sub-forum came to a successful conclusion

How to sort multiple fields and multiple values in sql statement

.NET应用程序--Helloworld(C#)
![[Filter tracking] based on matlab unscented Kalman filter inertial navigation + DVL combined navigation [including Matlab source code 2019]](/img/c9/fff226b6d33a773b59a0314a99a788.png)
[Filter tracking] based on matlab unscented Kalman filter inertial navigation + DVL combined navigation [including Matlab source code 2019]

Never put off till tomorrow what you can put - house lease management system based on the SSM

In 2022, you still can't "low code"?Data science can also play with Low-Code!

Use SuperMap iDesktopX data migration tool to migrate map documents and symbols

你要的七夕文案,已为您整理好!
随机推荐
tree table lookup
High Item 02 Information System Project Management Fundamentals
队列题目:最近的请求次数
(11) Metaclass
Kubernetes 网络入门
Distributed systems revisited: there will never be a perfect consistency scheme...
沃谈小知识 |“远程透传”那点事儿
Solve the problem of port occupancy Port xxxx was already in use
private package
Why is the pca component not associated
语法基础(变量、输入输出、表达式与顺序语句完成情况)
调用阿里云oss和sms服务
The pit of std::string::find return value
Intersection of Boolean Operations in SuperMap iDesktop.Net - Repairing Complex Models with Topological Errors
[Filter tracking] based on matlab unscented Kalman filter inertial navigation + DVL combined navigation [including Matlab source code 2019]
You may use special comments to disable some warnings. Three ways to report errors
The second council meeting of the Dragon Lizard Community was successfully held!Director general election, 4 special consultants joined
Turn: Charles Handy: Who you are is more important than what you do
Is your data safe in this hyperconnected world?
Syntax basics (variables, input and output, expressions and sequential statements)