Written in the beginning

  • Due to theviteThis build tool was used in vuE3 door, and its build idea is superior in my opinionwebpackThe bottom layer is also usedesbuild, the performance is better
  • So in order to take care of some of your friends who haven’t studied beforeviteLet’s see what isvite

What is a vite

  • Vite, a development server based on browser native ES Imports. Imports are parsed in the browser, compiled and returned on demand on the server side, bypashing the concept of packaging entirely, and the server is available on demand, supporting hot updates that don’t slow down as more modules grow. For production environments, the same code can be packaged in rollup
  • viteNatural advantages:
    • Quick cold start of the server
    • Instant Hot Module Replacement (HMR)
    • True on-demand compilation

How vite works

  • When declaring a script tag of type module
<script type="module" SRC ="/ SRC /main.js">Copy the code
  • The browser will initiate a GET like the serverhttp://localhost:3000/src/main.js request main. Js file:
// /src/main.js:
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
Copy the code
  • When the browser requests the main.js file and detects that it contains the package imported by import, it sends an HTTP request to its internal import reference to obtain the content file of the module
  • Such as:GET http://localhost:3000/@modules/vue.js
  • Such as: GET http://localhost:3000/src/App.vue
  • Its Vite’s main function is through the browser hijack the requests, and corresponding processing in the back-end will be used in the project file with a simple decomposition and integration, and then returned to the browser to render the page, not the packaging on file compiling Vite the process, so its running speed than the original webpack compilation speed a lot of development

Simple implementation of Vite

  • Due to the amount of code there are some large, I will not write their own, directly take someone else’s code over,

Juejin. Cn/post / 689811…

  • First, koA starts a listening port for accessing the hot update service
Function createServer() {let app = new Koa() const context = { Resolveplugin.foreach (plugin => plugin(context)) return app} // Run koA middleware (vite plugin) resolveplugin.foreach (plugin => plugin(context)) return app}  createServer().listen(4000, () => { })Copy the code
  • Write the corresponding plug-in processing
  • Module references are handled first, because browsers only have relative and absolute paths

Here, readBody is simply a method that reads a file stream, wrapped in a normal read stream method

Koa middleware processing
  • Override paths are dealt with first, because browsers only have absolute and relative paths
app.use(async (ctx, next) => { await next(); The static server middleware will place the result in ctx.body // The stream needs to be changed to a string, If (ctx.body && ctx.response.is('js')) {let r = await readBody(ctx.body); // vue => /@modules const result = rewriteImports(r); ctx.body = result; }})},Copy the code
  • After rewriting the path, you need to intercept it.vueFile and take@module(Before overwriting the pathnode_modulesThe files inside)
// 2. Intercept requests containing /@modules/vue, go to node_modules, import the corresponding module and return ({app, Root}) => {const reg = /^ // @modules/ / app.use(async (CTX, next)) => {// If (! reg.test(ctx.path)) { return next(); } const id = ctx.path.replace(reg, ''); let mapping = { vue: path.resolve(root, 'node_modules', '@vue/runtime-dom/dist/runtime-dom.esm-browser.js'), } const content = await fs.readFile(mapping[id], 'utf8'); ctx.type = 'js'; // The file returned is js ctx.body = content; })},Copy the code
  • After parsing the path, we need to parse the vue template file (same for react JSX code).
/ / 3. Parsing. Vue file ({app, root}) = > {app. Use (async (CTX, next) = > {the if (! ctx.path.endsWith('.vue')) { return next(); } const filePath = path.join(root, ctx.path); const content = await fs.readFile(filePath, 'utf8'); Const {compileTemplate, parse} = require(path.resolve(root, 'node_modules', '@vue/compiler-sfc/dist/compiler-sfc.cjs')) let { descriptor } = parse(content); if (! ctx.query.type) { //App.vue let code = '' if (descriptor.script) { let content = descriptor.script.content; code += content.replace(/((? :^|\n|;) \s*)export default/, '$1const __script='); } if (descriptor.template) { const requestPath = ctx.path + `? type=template`; code += `\nimport { render as __render } from "${requestPath}"`; code += `\n__script.render = __render` } code += `\nexport default __script` ctx.type = 'js'; ctx.body = code } if (ctx.query.type == 'template') { ctx.type = 'js'; let content = descriptor.template.content const { code } = compileTemplate({ source: content }); // Convert the template in app.vue to the render function ctx.body = code; Use (static(root)) app.use(static(path.resolve(root)) app.use(static(path.resolve(root)) 'public')))}] function createServer() {let app = new Koa() const context = { process.cwd() // C:\Users\... \my-vite-vue3} // Run the middleware resolvePlugin. ForEach (plugin => plugin(context)) return app}Copy the code
  • Here are two utility functions: one reads the stream and one overrides the path
Async function readBody(stream) {if (stream instanceof Readable) {return new Promise((resolve) => {let res  = '' stream.on('data', function (chunk) { res += chunk }); stream.on('end', function () { resolve(res) }) }) } else { return stream; }}Copy the code
  • Rewrite path middleware
Const resolvePlugin = [// 1. Add /@modules/vue to the path of the plugin, and the browser will send the request again ({app, root }) => { function rewriteImports(source) { let imports = parse(source)[0]; let ms = new MagicString(source);  if (imports.length > 0) { for (let i = 0; i < imports.length; i++) { let { s, e } = imports[i]; Let the id = source. Slice (s, e); / / application identification vue. / App. Or vue / / it isn't. / / if (/ ^ ^ \ / \] /. The test (id)) {id = ` / @ modules / ${id} `;  ms.overwrite(s, e, id) } } } return ms.toString(); }Copy the code
This is a simple Vite

Start using React

  • Vite is a new technology, and not popular in China at present, in order to avoid the pit, we directly use the official recommended template generation
npm init vite-app --template react
Copy the code
  • After the template generation is complete, run the command to start the project
yarn
yarn dev
Copy the code
  • Such areactThe project is set up and the default is17.0.0Version of thereactSo that thecreateElementMethods don’t have to be exported from React anymore, I thinkjsxStyle code will also be easier to migrate to other framework projects
"Dependencies" : {" react ", "^ 17.0.0", "the react - dom" : "^ 17.0.0"}, "devDependencies" : {" vite ": "^ 1.0.0 - rc. 13," "vite plugin - react" : "^ 4.0.0"}Copy the code
  • This template is generated by its own hot update, relatively simple, if you have special needs, you can use more plugin, set in viet.config.js
  • Default configuration
// @ts-check
import reactPlugin from 'vite-plugin-react'

/**
 * @type { import('vite').UserConfig }
 */
const config = {
  jsx: 'react',
  plugins: [reactPlugin]
}

export default config

Copy the code

Write in the last

  • This article is more aboutviteI haven’t used it in production yet
  • In my opinion,viteIf ecology gets going, maybe we don’t need itwepback6This version (of course the future is unknown)
  • After reading this article, you should have a clear understanding of how Vite works and react builds/ look atKeep an eye on [The front-end peakPublic account
References:
  • Juejin. Cn/post / 689811…

  • Juejin. Cn/post / 684490…

  • github.com/vitejs/vite