Big front-end study notes-Vite implementation principle

Vite implementation principle

Article content output source: big front-end high-paying training camp

1. Introduction to Vite

1. Vite concept

  • Vite is a lighter and faster web application development tool for modern browsers
  • It is implemented based on ECMAScript standard native module system (ES Modules)

2. Vite project dependencies

  • Quick
  • @ vue / compiler-sfc

3. Basic use

vite serve / vite build
Insert picture description here

There vite serveis no need to package during execution , and a web server is directly opened. When the browser requests the server, such as requesting a single-file component, then compile the single-file component on the server side, and then return the compiled result to the browser. Pay attention to this The compilation is on the server side, and the processing of the modules is handled on the server side from the request.

And execute vue-cli-service serve:
Insert picture description here

When it runs vue-cli-service serve, it will be used internally webpack. First, package all the modules. If the number of modules is large, the packaging speed will be very slow. The packaged result will be stored in the memory, and then the developed web server will be opened for browsing. The browser requests the web server, and returns the result of the package in memory directly to the browser. A tool like webpack uses all modules to be compiled and packaged into the bundle in advance, that is, regardless of whether the module is executed or used, Must be compiled and packaged into a bundle. As the project becomes larger and larger, the packaged bundle becomes larger and larger, and the packaging speed naturally becomes slower and slower.

Vite uses the modular feature of ESModule natively supported by modern browsers to omit the packaging of modules. For files that need to be compiled, such as single file components, style modules, etc., Vite uses another mode of instant compilation, which means that only When a file is specifically requested, the file will be compiled on the server side, so the benefits of this kind of just-in-time compilation are mainly reflected in the on-demand compilation, which will be faster.

4. HMR

  • Vite HMR
    • Immediately mutate the currently modified file
  • Webpack HMR
    • It will automatically rebuild with this file location entry, and all the dependencies involved will also be reloaded once, so the response speed will be slower

5. Build

  • Vite build
    • Rollup
    • Dynamic import
      • polyfill

6. Pack OR not pack

  • Two reasons to use Webpack packaging:
    • The browser environment does not support modularization (and now most browsers support ESM modularization)
    • Scattered module files will generate a large number of HTTP requests (HTTP2 can have long connections)

7. Browser support for ESModule

Modern browsers support ESModule modularity

8. Out of the box

  • TypeScript-built-in support
  • less/sass/stylus/postcss-built-in support (need to install separately)
  • JSX
  • Web Assembly

9. Vite features

  • Fast cold start
  • Module hot update
  • Compile on demand
  • Out of the box

Two, static web server

1. Vite core functions

  • Static web server
  • Compile single-file components: intercept modules that are not recognized by the browser and process them
  • HMR

Three, modify the path of the third-party module

Create two middleware. One middleware is to change the path in the import in the third-party module to load @modules/模块文件名, and the other middleware is to determine whether there is in the request path after the request comes, @modules/模块名称and if so, go node_modules loads the corresponding module

Fourth, load third-party modules

When the request comes, judge whether the request path @modulesstarts with, if so, go to node_modules to load the corresponding module

Five, compile single file components

Send two requests, the first request is to compile the single-file component into an object, the second request is to compile the template of the single-file component, return a render function, and mount the render function to the object's render method.

Final code:

#!/usr/bin/env node
const 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 streamToString = stream => 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
}

// 3. 加载第三方模块。判断请求路径中是否以`@modules`开头,如果是的话,去node_modules加载对应的模块
app.use(async (ctx, next) => {
    
    
  // ctx.path --> /@modules/vue
  if (ctx.path.startsWith('/@modules/')) {
    
    
    const moduleName = ctx.path.substr(10)
    const pkgPath = path.join(process.cwd(), 'node_modules', moduleName, 'package.json')
    const pkg = require(pkgPath)
    ctx.path = path.join('/node_modules', moduleName, pkg.module)
  }
  await next()
})

// 1. 开启静态文件服务器
app.use(async (ctx, next) => {
    
    
  await send(ctx, ctx.path, {
    
    
    root: process.cwd(),
    index: 'index.html'
  })
  await next()
})

// 4. 处理单文件组件
app.use(async (ctx, next) => {
    
    
  if(ctx.path.endsWith('.vue')) {
    
    
    const contents = await streamToString(ctx.body)
    const {
    
     descriptor } = compilerSFC.parse(contents) // 返回一个对象,成员descriptor、errors
    let code
    if (!ctx.query.type) {
    
     // 第一次请求,把单文件组件编译成一个对象
      code = descriptor.script.content
      // console.log('code', code)
      code = code.replace(/export\s+default\s+/g, 'const __script = ')
      code += `
import { render as __render } from "${
      
      ctx.path}?type=template"
__script.render = __render
export default __script
      `
    } else if (ctx.query.type === 'template') {
    
    
      const templateRender = compilerSFC.compileTemplate({
    
     source: descriptor.template.content })
      code = templateRender.code
    }
    ctx.type = 'application/javascript'
    ctx.body = stringToStream(code) // 转化成流
  }
  await next()
})

// 2. 修改第三方模块的路径
app.use(async (ctx, next) => {
    
    
  if (ctx.type === 'application/javascript') {
    
    
    const contents = await streamToString(ctx.body)
    // import vue from 'vue'
    // import App from './App.vue'
    ctx.body = contents
    .replace(/(from\s+['"])(?![\.\/])/g, '$1/@modules/') // 分组匹配,第一个分组中,from原样匹配form,\s+匹配一至多个空格,['"]匹配单引号或双引号。第二个分组中,?!标识不匹配这个分组的结果,也就是排除点开头或者\开头的情况
    .replace(/process\.env\.NODE_ENV/g, '"development"')// 替换process对象
  }
})


app.listen(4000)
console.log('Server running @ http://localhost:4000')

When using, first link the cli project to the global,npm link

Then execute the my-vite-clirun project in the vue3 project. The image and style module import code in vue3 is commented out.
Insert picture description here

Guess you like

Origin blog.csdn.net/jal517486222/article/details/108689712