当前位置:网站首页>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
全文终…
边栏推荐
- shell脚本:for循环与while循环
- IJCAI2022 | DictBert: Pre-trained Language Models with Contrastive Learning for Dictionary Description Knowledge Augmentation
- ASP.NET应用程序--Hello World
- Web3.0 Dapps——通往未来金融世界的道路
- Object.defineProperty monitors data changes in real time and updates the page
- 【七夕节】浪漫七夕,代码传情。将爱意变成绚烂的立体场景,给她(他)一个惊喜!(送代码)
- 2022-08-04 The sixth group, hidden from spring, study notes
- How to find all fields with empty data in sql
- Syntax basics (variables, input and output, expressions and sequential statement completion)
- 队列题目:最近的请求次数
猜你喜欢
2022-08-04T17:50:58.296+0800 ERROR Announcer-3 io.airlift.discovery.client.Announcer appears after successful startup of presto
使用二维码传输文件的小工具 - QFileTrans 1.2.0.1
Multithreading (2)
Never put off till tomorrow what you can put - house lease management system based on the SSM
The Tanabata copywriting you want has been sorted out for you!
Simple description of linked list and simple implementation of code
Web3.0 Dapps——通往未来金融世界的道路
【滤波跟踪】基于matlab无迹卡尔曼滤波惯性导航+DVL组合导航【含Matlab源码 2019期】
[Solved] Unity Coroutine coroutine is not executed effectively
静态方法获取配置文件数据
随机推荐
从“能用”到“好用” 国产软件自主可控持续推进
冒泡排序与快速排序
mysql can't Execute, please solve it
剑指Offer--找出数组中重复的数字(三种解法)
rpc-remote procedure call demo
十五. 实战——mysql建库建表 字符集 和 排序规则
Likou - preorder traversal, inorder traversal, postorder traversal of binary tree
sql怎么找字段里所有数据为空的字段
Everyone in China said data, you need to focus on core characteristic is what?
Slapped in the face: there are so many testers in a certain department of byte
sql server installation prompts that the username does not exist
【已解决】Unity Coroutinue 协程未有效执行的问题
QT language file production
burp安装及代理设置
1667. Fix names in tables
你要的七夕文案,已为您整理好!
Getting Started with Kubernetes Networking
腾讯云【Hiflow】新时代自动化工具
用CH341A烧录外挂Flash (W25Q16JV)
【 genius_platform software platform development 】 : seventy-six vs the preprocessor definitions written cow force!!!!!!!!!!(in the other groups conding personnel told so cow force configuration to can