In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-04 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces the principle of Vite analysis, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor with you to understand.
1. Overview
Vite is a lighter and faster web application development tool for modern browsers. The bottom layer is implemented based on the ECMAScript standard native module system ES Module. The purpose of his appearance is to solve the problems such as the long cold start time of webpack and the slow reaction speed of Webpack HMR hot update.
By default, the project created by Vite is a normal Vue3 application with fewer configuration files and dependencies than applications created based on Vue-cli.
The projects created by Vite require very few development dependencies, only Vite and @ vue/compiler-sfc. Here Vite is a running tool, and compiler-sfc is to compile a single-file component at the end of .vue. You can also support the use of other frameworks such as React when creating a project by specifying a different template. After the project is created, it can be started and packaged with two commands.
# enable server vite serve# to package vite build
It is precisely because the web service started by Vite does not need to be compiled and packaged, so it starts very quickly, and most of the code running in the debugging phase is the code you write in the editor, which is much faster than webpack's compilation and re-rendering. Of course, the production environment still needs to be packaged, after all, many times the latest ES specification we use is not supported in browsers, and Vite's packaging process is similar to webpack, which compiles and packages all files together. The requirement of Vite for code cutting is realized by native dynamic import, so the packaging result can only support modern browsers. If you need to be compatible with older browsers, you can introduce Polyfill.
In addition to using Webpack packaging because the browser environment does not support modularity and new syntax, module files generate a large number of http requests. If you use a modular approach to development, a page will have a dozen or even dozens of modules, and many times there will be several kb files, open a page to load dozens of js resources, which is obviously unreasonable.
Projects created by Vite require almost no additional configuration. TS, Less, and Sass,Stylus,postcss are already supported by default, but the corresponding compilers need to be installed separately, as well as jsx and Web Assembly by default.
The advantage of Vite is to enhance the developer's experience in the development process, the web development server does not need to wait to start immediately, the module hot update is almost real-time, and the required files will be compiled on demand to avoid compiling files that are not needed. And out of the box to avoid the configuration of loader and plugins.
The core functions of Vite include opening a static web server, compiling single-file components and providing HMR functions. When you start vite, you will first use the current project directory as the root directory of the static server, which will intercept some requests, compile in real time when requesting a single file, and deal with modules that other browsers cannot recognize, and achieve hmr through websocket.
two。 Implement a static test server
First of all, implement a command line tool that can open a static web server. Koa is used internally by vite1.x to implement static servers. (the ps:node command line tool can check out my previous article, but I won't cover it here and just post the code.)
Npm initnpm install koa koa-send-D
The entry file of the tool bin is set to the local index.js
#! / usr/bin/env nodeconst Koa = require ('koa') const send = require (' koa-send') const app = new Koa () / / Open static file server app.use (async (ctx, next) = > {/ / load static file await send (ctx, ctx.path, {root: process.cwd ()) Index: 'index.html'}) await next ()}) app.listen (5000) console.log (' server has started http://localhost:5000')
In this way, a tool for node static server is written.
3. Deal with third-party modules
Our approach is that when a third-party module (a file in node_modules) is used in the code, you can change the path of the third-party module to give it an identity, and then get the identity in the server to deal with the module.
First of all, the path of the third-party module needs to be modified, and a new middleware is needed to implement it. To determine whether the file currently returned to the browser is javascript, just look at the content-type in the response header. If it is javascript, you need to find the module path introduced in this file. Ctx.body is the content file returned to the browser. The data here is a stream that needs to be converted to a string to process.
Const stream2string = (stream) = > {return new Promise ((resolve, reject) = > {const chunks = [] Stream.on ('data', chunk = > {chunks.push (chunk)}) stream.on (' end', () = > {resolve (Buffer.concat (chunks) .toString ('utf-8')}) stream.on (' error', reject)})} / / modify the third-party module path app.use (async (ctx) Next) = > {if (ctx.type = 'application/javascript') {const contents = await stream2string (ctx.body) / / modify the imported path in body, re-assign the value to body and return it to the browser / / import vue from 'vue', match to from' modified to from'@ modules/ ctx.body = contents.replace (/ (from\ s + ['") (?! [\.\ /]) / g,'$1Compact modulesAccord');}})
Then start loading the third-party module. Here you also need a middleware to determine whether the request path starts with a modified @ module. If so, load the corresponding module in node_modules and return it to the browser. The middleware should be placed in front of the static server.
/ / load third-party module app.use (async (ctx, next) = > {if (ctx.path.startsWith ('/ @ modules/')) {/ / intercept module name const moduleName = ctx.path.substr (10);}})
After getting the module name, you need to obtain the module entry file. To obtain the entry file of the ES Module module, you need to find the package.json of the module and then obtain the value of the module field in the package.json, that is, the entry file.
/ / find the module path const pkgPath = path.join (process.pwd (), 'node_modules', moduleName,' package.json'); const pkg = require (pkgPath); / / re-assign to ctx.path, you need to reset an existing path, because the previous path does not exist ctx.path = path.join ('/ node_modules', moduleName, pkg.module); / / execute the next middleware awiat next ()
In this way, although the browser request comes in with the @ modules path, before loading, modify the path path to the path in node_modules, so that when loading, you will go to node_modules to get the file and respond to the loaded content to the browser.
Load third-party modules:
App.use (async (ctx, next) = > {if (ctx.path.startsWith ('/ @ modules/')) {/ / intercept module name const moduleName = ctx.path.substr (10); / / find module path const pkgPath = path.join (process.pwd (), 'node_modules', moduleName,' package.json'); const pkg = require (pkgPath) / / to re-assign ctx.path, you need to reset an existing path, because the previous path does not exist ctx.path = path.join ('/ node_modules', moduleName, pkg.module); / / execute the next middleware awiat next ();}}) 4. Single file component processing
As mentioned earlier, browsers cannot handle .vue resources. Browsers can only recognize common resources such as js and css, so other types of resources need to be processed on the server side. When requesting a single-file component, the single-file component needs to be compiled into a js module on the server and returned to the browser.
So here when the browser requests App.vue for the first time, the server compiles the single-file component into an object, loads the component, and then creates an object.
Import Hello from'. / src/components/Hello.vue'const _ _ script = {name: "App", components: {Hello}}
Then load the entry file, this time tell the server to compile the template for the single-file component and return a render function. Then mount the render function to the component option object you just created, and finally export the option object.
Import {render as _ _ render} from'/ src/App.vue?type=template'__script.render = _ _ render__script.__hmrId ='/ src/App.vue'export default _ _ script
In other words, vite sends two requests, the first request compiles a single file, and the second request compiles a single file template to return a render function.
Compile single file options:
First, let's implement the case of requesting a single file for the first time. The single-file component needs to be compiled into an option, which is also implemented with a middleware. This feature needs to be done after dealing with the static server and before processing the third-party module path.
First of all, you need to compile the single-file component with the help of compiler-sfc.
/ / process single file component app.use (async (ctx, next) = > {if (ctx.path.endsWith ('.vue')) {/ / get the response file content and convert it into the string const contents = await streamToString (ctx.body); / / compile the file content const {descriptor} = compilerSFC.parse (contents); / / define the status code let code / / if type does not exist, it is the first time to request if (! ctx.query.type) {code = descriptor.script.content / / the code format here needs to be modified into the vite we posted earlier / / import Hello from'. / components/Hello.vue' / / export default {/ / name: 'App' / / components: {/ / Hello /} / /} / / modify the format of code Replace export default with const _ _ script = code = code.relace (/ export\ s+default\ ssteps _ g 'const _ _ script =') code + = `import {render as _ render} from'${ctx.path}? type=template' _ _ script.rener = _ _ render export default _ _ script `} / / set the browser response header to js ctx.type = 'application/javascript' / / Converts a string into a data stream and passes it to the next middleware. Ctx.body = stringToStream (code);} await next ()} const stringToStream = text = > {const stream = new Readable (); stream.push (text); stream.push (null); return stream;} npm install @ vue/compiler-sfc-D.
Then let's deal with the second request of the single-file component, the second request url takes the type=template parameter, and the single-file component template needs to be compiled into a render function.
First, you need to determine whether there is a type=template in the current request.
If (! ctx.query.type) {...} else if (ctx.query.type = 'template') {/ / get the compiled object code is the render function const templateRender = compilerSFC.compileTemplate ({source: descriptor.template.content}) / / assign the render function to code and return it to the browser code = templateRender.code}
Here we will also deal with the process.env in the tool, because the code will be returned to the browser to run, and if it is not handled, it will default to node causing the run to fail. You can modify it in the middleware that modifies the path of the third-party module, and then add a modified process.env after modifying the path.
/ / modify the third-party module path app.use (async (ctx, next) = > {if (ctx.type = 'application/javascript') {const contents = await stream2string (ctx.body) / / modify the imported path in body, re-assign the value to body and return it to the browser / / import vue from 'vue', match to from' modified to from'@ modules/ ctx.body = contents.replace (/ (from\ s + ['") (?! [\.\ /]) / g,'$1 replace (/ process\ .env\ .Node _ ENV/g,'" development ");})
So far, we have implemented a simplified version of vite, of course, we only demonstrated .vue files here, and we did not deal with other resources such as css,less, but the methods are similar, and students who are interested can implement them on their own.
#! / usr/bin/env nodeconst path = require ('path') const {Readable} = require (' stream) const Koa = require ('koa') const send = require (' koa-send') const compilerSFC = require ('@ vue/compiler-sfc') const app = new Koa () const stream2string = (stream) = > {return new Promise ((resolve, reject) = > {const chunks = [] Stream.on ('data', chunk = > {chunks.push (chunk)}) stream.on (' end', () = > {resolve (Buffer.concat (chunks) .toString ('utf-8')}) stream.on (' error', reject)})} const stringToStream = text = > {const stream = new Readable (); stream.push (text); stream.push (null); return stream } / / load third-party module app.use (async (ctx, next) = > {if (ctx.path.startsWith ('/ @ modules/')) {/ / intercept the module name const moduleName = ctx.path.substr (10); / / find the module path const pkgPath = path.join (process.pwd (), 'node_modules', moduleName,' package.json'); const pkg = require (pkgPath) / / to re-assign ctx.path, you need to reset an existing path, because the previous path does not exist ctx.path = path.join ('/ node_modules', moduleName, pkg.module); / / execute the next middleware awiat next () }}) / / Open static file server app.use (async (ctx, next) = > {/ / load static file await send (ctx, ctx.path, {root: process.cwd (), index: 'index.html'}) await next ()}) / / process single file component app.use (async (ctx) Next) = > {if (ctx.path.endsWith ('.vue')) {/ / get the contents of the response file Convert to the string const contents = await streamToString (ctx.body) / / compile file content const {descriptor} = compilerSFC.parse (contents); / / define status code let code; / / if type does not exist, it is the first time to request if (! ctx.query.type) {code = descriptor.script.content / / the code format here needs to be modified into the vite we posted earlier / / import Hello from'. / components/Hello.vue' / / export default {/ / name: 'App' / / components: {/ / Hello /} / /} / / modify the format of code Replace export default with const _ _ script = code = code.relace (/ export\ s+default\ ssteps _ g 'const _ _ script =') code + = `import {render as _ render} from'${ctx.path}? type=template' _ _ script.rener = _ _ render export default _ _ script `} else if (ctx.query.type = 'template') {/ / get the compiled object code is render The function const templateRender = compilerSFC.compileTemplate ({source: descriptor.template.content}) / / assigns the render function to code and returns it to the browser code = templateRender.code} / / sets the browser response header to js ctx.type = 'application/javascript' / / converts a string into a data stream and passes it to the next middleware. Ctx.body = stringToStream (code);} await next ()}) / / modify the third-party module path app.use (async (ctx, next) = > {if (ctx.type = = 'application/javascript') {const contents = await stream2string (ctx.body)) / / modify the imported path in body, re-assign the value to body and return it to the browser / / import vue from 'vue', match to from' modified to from'@ modules/ ctx.body = contents.replace (/ (from\ s + ['") (?! [\.\ /]) / g,'$1 replace (/ process\ .env\ .Node _ ENV/g,'" development "') }}) app.listen (5000) console.log ('the server has started http://localhost:5000')) Thank you for reading this article carefully. I hope the article "Analysis of the principles of Vite" shared by the editor will be helpful to you. At the same time, I also hope that you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.