Vite原理

Vite

注意解决webpack开发时候慢的问题。Vite原理_第1张图片
Vite原理_第2张图片
Vite原理_第3张图片
原理
只有使用了才去请求文件或模块
Vite原理_第4张图片
vuecli的原理
不管模块是否被使用都被打包到bundle里
Vite原理_第5张图片
vite的HMR
Vite原理_第6张图片
build
Vite原理_第7张图片
延伸问题
现在应用是否需要打包?
Vite原理_第8张图片
问题1 现在浏览器都支持ESM
问题2 现在http可以解决多请求问题

vie支持其他和特性
Vite原理_第9张图片
Vite原理_第10张图片

Vite原理

Vite原理_第11张图片
代码

#!/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. 加载第三方模块
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)
    let code
    if (!ctx.query.type) {
     
      code = descriptor.script.content
      // console.log(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/')
      .replace(/process\.env\.NODE_ENV/g, '"development"')
  }
})

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

Vite 实现原理-修改路径

因为路径原因请求会报错,需要特殊处理

// 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/')
      .replace(/process\.env\.NODE_ENV/g, '"development"')
  }
})

Vite 实现原理-加载第三方模块

// 3. 加载第三方模块
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()
})

Vite 实现原理-编译单文件组件


// 4. 处理单文件组件
app.use(async (ctx, next) => {
     
  if (ctx.path.endsWith('.vue')) {
     
    const contents = await streamToString(ctx.body)
    const {
      descriptor } = compilerSFC.parse(contents)
    let code
    if (!ctx.query.type) {
     
      code = descriptor.script.content
      // console.log(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()
})

Vite 实现原理-加载第三方模块

在这里插入代码片

核心就是不本地打包,服务器编译单文件组件

你可能感兴趣的:(vue3)