当前位置:网站首页>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
全文终…
边栏推荐
- 【软件测试】自动化测试之unittest框架
- Open Source License Description LGPL
- 用CH341A烧录外挂Flash (W25Q16JV)
- sql server installation prompts that the username does not exist
- Getting Started with Kubernetes Networking
- Cybersecurity and the Metaverse: Identifying Weak Links
- Common open source databases under Linux, how many do you know?
- 【七夕节】浪漫七夕,代码传情。将爱意变成绚烂的立体场景,给她(他)一个惊喜!(送代码)
- How to Add Category-Specific Widgets in WordPress
- Question about #sql shell#, how to solve it?
猜你喜欢

mysql can't Execute, please solve it
![[Solved] Unity Coroutine coroutine is not executed effectively](/img/ab/035ef004a561fb98d3dd1d7d8b5618.png)
[Solved] Unity Coroutine coroutine is not executed effectively

Use Unity to publish APP to Hololens2 without pit tutorial

人人都在说的数据中台,你需要关注的核心特点是什么?

public static <T> List<T> asList(T... a) 原型是怎么回事?

Why did they choose to fall in love with AI?

2022 High-level installation, maintenance, and removal of exam questions mock exam question bank and online mock exam

After the large pixel panorama is completed, what are the promotion methods?

CPDA|How Operators Learn Data Analysis (SQL) from Negative Foundations

用Unity发布APP到Hololens2无坑教程
随机推荐
Multithreading (2)
Android实战开发-Kotlin教程(入门篇-登录功能实现 3.3)
High Item 02 Information System Project Management Fundamentals
On governance and innovation, the 2022 OpenAtom Global Open Source Summit OpenAnolis sub-forum came to a successful conclusion
In 2022, you still can't "low code"?Data science can also play with Low-Code!
Likou - preorder traversal, inorder traversal, postorder traversal of binary tree
运维监控系统之Open-Falcon
Syntax basics (variables, input and output, expressions and sequential statements)
十五. 实战——mysql建库建表 字符集 和 排序规则
rpc-remote procedure call demo
The linear table lookup
Web3.0 Dapps——通往未来金融世界的道路
Summary of domestic environments supported by SuperMap
Native js realizes the effect of selecting and canceling all the multi-select boxes
2022-08-04 The sixth group, hidden from spring, study notes
undo problem
ffmpeg -sources分析
Countdown to 2 days|Cloud native Meetup Guangzhou Station, waiting for you!
How to sort multiple fields and multiple values in sql statement
After the large pixel panorama is completed, what are the promotion methods?