小狐狸学Vite(六、预编译并保存metadata信息)

945 阅读2分钟

“我正在参加「掘金·启航计划」”

文章导航

一、核心知识

二、实现命令行+三、实现http服务器

四、实现静态文件中间件

五、分析第三方依赖

六、预编译并保存metadata信息

这小结主要要做的就是对第三方依赖信息进行一个预编译,并生成缓存信息存放在本地,从而加快后序开发环境启动的速度。

1.将metadata信息挂载到server上面

lib\server\index.js

async function runOptimize(config, server) {
+  const optimizeDeps = await createOptimizeDepsRun(config)
  // 把生成的优化信息保存在 server 上面 
+  server._optimizeDepsMetadata = optimizeDeps.metadata
}

2. 添加缓存目录

const path = require('path')
const { normalizePath } = require("./utils")

async function resolveConfig() {
  // 获取当前进程执行的目录
  let root = normalizePath(process.cwd())
  // 存放预编译的信息
+  const cacheDir = normalizePath(path.resolve(`node_modules/.vite3`))
  let config = {
    root,
 +   cacheDir
  }
  return config
}

module.exports = resolveConfig

3.根据deps信息打包第三方依赖

lib\optimizer\index.js

const { build } = require('esbuild')
const path = require('path')
const fs = require('fs-extra')
const { normalizePath } = require('../utils')
const scanImports = require('./scan')

// 这里使用 esbuild 扫描项目依赖了那些模块(第三方依赖或者自己写的模块)

async function createOptimizeDepsRun(config) {
  // 使用 esbuild 获取依赖信息
  const deps = await scanImports(config)
  // 从配置信息中拿到 缓存目录
  const { cacheDir } = config
  // 生成缓存目录
  const depsCacheDir = path.resolve(cacheDir, 'deps')
  // 生成 _metadata.json 文件的路径
  const metadataPath = path.join(depsCacheDir, 'metadata.json')
  const metadata = {
    optimized: {}
  }
  // 遍历收集到的第三方依赖信息
  for (const id in deps) {
    // 真实路径
    const entry = deps[id]
    metadata.optimized[id] = {
      file: normalizePath(path.resolve(depsCacheDir, id + '.js')),
      src: entry
    }
    // 调用 esbuild 进行真正的预打包
    await build({
      absWorkingDir: process.cwd(),
      entryPoints: [entry],
      outfile: path.resolve(depsCacheDir, id + '.js'),
      bundle: true,
      write: true,
      format: 'esm'
    })
  }
  await fs.ensureDir(depsCacheDir);
  await fs.writeFile(metadataPath, JSON.stringify(metadata, (key, value) => {
    if (key === 'file' || key === 'src') {
      // 生成相对缓存目录的路径
      return normalizePath(path.relative(depsCacheDir, value))
    }
    return value
  }, 2))  // 两个空格缩进

  return { metadata }
}

exports.createOptimizeDepsRun = createOptimizeDepsRun

4.最终生成的metadata信息

image.png

{
  "optimized": {
    "vue": {
      "file": "vue.js",
      "src": "../../vue/dist/vue.runtime.esm-bundler.js"
    },
    "lodash": {
      "file": "lodash.js",
      "src": "../../lodash/lodash.js"
    }
  }
}

现在我们已经将第三方依赖编译到缓存目录下面了,后序当在项目中使用到了第三方依赖的时候,就会直接使用预编译好的依赖文件了,下一节会写到 ing

点赞 👍

通过阅读本篇文章,如果有收获的话,可以点个赞,这将会成为我持续分享的动力,感谢~