concept
Esm based (browser native ES Module support)
- Vite, a development server based on the browser native ES module. Using the browser to parse the module, compiling and returning it on demand on the server side, bypassing the concept of packaging completely and allowing the server to be used on demand. There is also Vue file support, and hot updates are handled, and the speed of hot updates does not slow down as modules increase.
- Vite requires that the project consists entirely of ES module modules. The common.js module cannot be used directly on Vite. Therefore, it cannot be used directly in a production environment. Traditional packaging tools like rollup are still used for packaging.
- The basic implementation of Vite is to start a KOA server to intercept browser requests for the ES module. Finally, the file is returned to the client in ES module format after certain processing
Implementation steps
Start a KOA server and process the homepage (index.html), JS files, and bare modules such as “vue” and vUE files separately
- Return index.html, then load main.js from index.html, and load other files from main.js
- Load a bare module in main.js, such as “vue”, and vite will prepack the contents of the vue module into node_modules, then replace the path
Import {createApp} from ‘vue’ converts to import {createApp} from ‘/@modules/vue’ and returns the relative address of node_module with /@modules. Load the vue file. When Vite encounters a file with a. Vue suffix, use the Compiler method in VUE to parse and return. Due to the particularity of the. Vue template file, it is divided into three modules (Template, CSS, script module) for processing respectively. Then you put script, template, CSS and send multiple requests to get it.
File execution order in VUE
Localhost == “client(websocket) ==> main.js ==> env.js ==> vue. Js (bare module vue) ==> app.vue ==
Principle of thermal renewal
The hot loading principle of Vite is that a Websocket link is established between the client and the server. When the code is modified, the server sends a message to inform the client to request the modification of the module code and complete the hot update. The client file will be executed after localhost. This is where webcocket is set up to implement hot update, and then main.js
Server Principles
What the server does is listen for changes to the code file and, when appropriate, send websocket messages to inform the client to request new module code.
Client Principles
Vite’s websocket-related code is written into the code while processing HTML
Simple Vite code implementation
/src/app.vue
<template> <div>{{ title }}</div> </template> <script> import { ref } from "vue"; export default { setup() { const title = ref("hello, kvite!" ); return { title }; }}; </script>Copy the code
src/main.js
import {createApp} from 'vue'
import App from "./app.vue"
createApp(App).mount('#app')
Copy the code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>kvite</title>
</head>
<body>
<div id="app"></div>
<script>
window.process = {
env:{
NODE_ENV:'dev'
}
}
</script>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Copy the code
kvite.js
const Koa = require('koa') const app = new Koa() const opn = require('opn'); Const fs = require("fs") const path = require("path") const complierSFC = require('@vue/compiler-sfc' Use (async (CTX) => {const {url, Query} = ctx.request if (url === '/') {// Load index.html ctx.type = "text/ HTML "; ctx.body = fs.readFileSync(path.join(__dirname, "./index.html"), "utf8"); } else if (url.endswith ('.js')) {const p = path.join(__dirname, url) ctx.type = 'application/javascript' ctx.body = rewriteImport(fs.readFileSync(p, 'utf8'))} else if (url.startswith ("/@modules/")) {// bare moduleName const moduleName = url.replace("/@modules/", ""); // go to node_modules and find const prefix = path.join(__dirname, "./node_modules", moduleName); //package.json const module = require(prefix + "/package.json").module; const filePath = path.join(prefix, module); const ret = fs.readFileSync(filePath, "utf8"); Ctx.type = 'application/javascript' ctx.body = rewriteImport(ret)} else if (url.indexof ('.vue') > -1) {// Get the file path to load const p = path.join(__dirname, url.split("?" ) [0]); const ret = complierSFC.parse(fs.readFileSync(p, 'utf8')); // console.log(ret) is an AST tree. You can check if (! Query. Type) {/ / SFC request, read the vue file, the content of the resolution to get the js / / script part const scriptContent = ret. Descriptor. The script. The content; // Replace const script = scriptContent.replace("export default ", "const __script = "); // Replace const script = scriptContent.replace("export default ", "const __script = "); Ctx. type = 'application/javascript' ctx.body = '${rewriteImport(script)} // parse template import {render as __render} from '${url}? type=template' __script.render = __render export default __script `; } else if (query.type === "template") { const tpl = ret.descriptor.template.content; // compile const render = complierdom.compile (TPL, {mode: "module"}).code; Ctx. type = 'application/javascript' ctx.body = rewriteImport(render)}}}) It precompiles the required modules into node_modules, and then finds and loads them using the relative address. // Here we find modules by identifying /@modules. //import xx from "vue" ==> import xx from "/@modules/vue" function rewriteImport(content) {return content.replace(/ from ['"](.*)['"]/g, function (s1, s2) { if (s2.startsWith("./") || s2.startsWith("/") || s2.startsWith(".. /")) {return s1} else {return 'from '/@modules/${s2}''}})} app.listen(6666, () => { console.log('kvite start'); opn(`http://localhost:6666/`); })Copy the code
The code address
Vite works and realizes the video address by hand
Problems with vite in use
Qs-stringfy is not compatible with vite
The require module cannot be used; import.meta.glob is required
Vite plug-in
Plug-in case
/plugins/vite-plugin-my-example.ts export default function myExample () {return {name: plugins/vite-plugin-my-example.ts export default function myExample () { 'my - example, / / name for warnings and errors show / / enforce:' pre '|' post '/ / initializes the hooks, go only once in the options (opts) {the console. The log (' options' opts); }, buildStart() { console.log('buildStart'); }, config(config) { console.log('config', config); return {} }, configResolved(resolvedCofnig) { console.log('configResolved'); }, configureServer(server) { console.log('configureServer'); // server.app.use((req, res, next) => { // // custom handle request... // }) }, transformIndexHtml(html) { console.log('transformIndexHtml'); return html // return html.replace( // /<title>(.*?) <\/title>/, // `<title>Title replaced! </title> '//)}, // id confirm resolveId (source) {if (source === 'virtual-module') {console.log('resolvedId', source); return source; } return null; // Vite no longer asks other plug-ins to handle the id request. Load (id) {if (id === 'virtual-module') {console.log('load'); return 'export default "This is virtual!" '; } return null; Transform (code, id) {if (id === 'virtual-module') {console.log('transform'); } return code }, }; }Copy the code
Ts import myExample from './plugins/vite-plugin-my-example' // export default defineConfig({plugins: [vue(), myExample()], // plug-in}) // When the project runs, you can see the plug-in hook executingCopy the code
Vite plugin development guide video address
Vitejs official website address