Vite 记录

289 阅读3分钟

vite 预加载

路径补全

在处理import _ from "lodash这种非绝对路径相对路径的引用时,会触发路径补全:import _ from "/node_modules/.vite/deps/lodash,会补全类似 /node_modules/.vite/deps,以实际情况为准

找寻依赖的过程是自当前目录依次向上查找的过程,直到寻到根目录或者搜寻到对应依赖为止/user/node_modules/lodash

开发:yarn dev ---> 开发(每次依赖预构建所重新构建的相对路径都是正确的) 生产:vite会全权交给一个叫做 rollup 的库去完成生产环境

依赖预构建

首先 vite 会找到对应的依赖,然后调用 esbuild (对js语法进行处理的一个库),将其他规范的代码转换成 esmodule 规范,然后放到当前目录下的 node modules/.vite/deps,同时对 esmodule 规范的各个模块进行统一集成

以 lodash-es 为例: image.png

export { default as after } from "./after.js";
// 等价
import after1 from "./after.js";
export const after = after1;

将直接引用改成函数形式 image.png 在 vite.config.js 文件做如下配置,取消 esmodule 转换

export default {
  optimizeDeps: {
    exclude: ["lodash-es"]
  }
}

image.png 解决了3个问题:

  1. 不同的第三方包会有不同的导出格式(这个是 vite 没法约束人家的事情)
  2. 对路径的处理上可以直接使用 .vite/deps,方便路径重写
  3. 网络多包传输的性能问题(也是原生esmoduLe规范不敢支持node modules的原因之一),有了依赖预构建以后无论他有多少的额外exoort 和import,vite 尽可能的集成最后只生成一个或者几个模块

path.resolve 记录

函数作用:兼容各种文件路径拼接:./,../,\a\b等

  • __dirname: 该文件的根路径
  • process.cwd():node 运行根路径

插件

钩子函数

链接 cn.vitejs.dev/guide/api-p…

config

解析 Vite 配置前调用,接收原始用户配置和一个描述配置环境的变量

transformIndexHtml

转换 index.html 的专用钩子。最后修改 index.html文件机会,钩子接收当前的 HTML 字符串和转换上下文

configureServer

配置开发服务器的钩子,可以拦截请求,做 mock 返回

常用插件

vite-aliases

使用了 config 钩子,插件作用:检测 src 目录下的所有文件夹,并帮助我们去生成别名

// vite.config.js 版本差异注意导入方式
import { ViteAliases } from "./node_modules/vite-aliases" // 版本 0.11.7
import { ViteAliases } from "vite-aliases" // 版本 0.9.2

实现代码

const fs = require('fs');
const path = require('path');

function diffDirAndFile (dirFilesArr = [], basePath = "") {
  const result = {
    dirs: [],
    files: []
  }
  dirFilesArr.forEach(name => {
    const currentFileStat = fs.statSync(path.resolve(__dirname, basePath + '/' + name))
    // console.log('file stat=', name, currentFileStat.isDirectory())
    const isDir = currentFileStat.isDirectory()

    if (isDir) {
      result.dirs.push(name)
    } else {
      result.files.push(name)
    }
  })
  
  return result
}

function getTotalSrcDir (keyName) {
  const result = fs.readdirSync(path.resolve(__dirname, '../src'));
  const diffResult = diffDirAndFile(result, "../src");
  // console.log(diffResult)
  const resolveAliasesObj = {}
  diffResult.dirs.forEach(dirName => {
    const key = keyName +  dirName
    const absPath = path.resolve(__dirname, "../src" + "/" + dirName)
    resolveAliasesObj[key] = absPath
  })
  
  return resolveAliasesObj
}

module.exports = ({
  keyName = '@'
} = {}) => {
  return {
    config(config, env) {
      // console.log('config=', config);
      // console.log('env=', env);
      const resolveAliasesObj = getTotalSrcDir(keyName)
      // console.log('resolveAliasesObj=', resolveAliasesObj)
      return { 
        resolve: {
          alias: resolveAliasesObj
        }
      }
    }
  }
}

vite-plugin-html

使用了transformIndexHtml 钩子,插件作用:转换 index.html 文件 实现代码

module.exports = (options) => {
  // console.log(options)
  return {
    name: 'html-transform',
    transformIndexHtml(html) {
      // console.log('transformIndexHtml', html);
      return html.replace(/<%= title %>/g, options.inject.data.title)
    },
  }
}

VitePluginMock

使用了 configureServer 钩子,插件作用:配置 mock 实现代码

import path from 'path';

const fs = require('fs');

export default (options) => {
  return {
    configureServer (server) {
      // console.log(options)
      const mockStat = fs.statSync('mock')
      const isDirectory = mockStat.isDirectory()
      let mockResult = []
      if (isDirectory) {
        mockResult = require(path.resolve(process.cwd(), 'mock/index.js'))
        // console.log('mockResult',mockResult)
      }
      server.middlewares.use((req, res, next) => {
        // console.log('req', req.url)
        const matchItem = mockResult.find(mockDescriptor => mockDescriptor.url === req.url)
        if (matchItem) {
          const responseData = matchItem.response(req)
          res.setHeader('Content-Type', 'application/json')
          res.end(JSON.stringify(responseData))
        } else {
          next()
        }
        
      })
    }
  }
}

构建优化

分包策略

将 node_modules 或修改不多的文件单独打包

// vite-config.js
export default defineConfig({
    build: {
        rollupOptions: {
          output: {
            manualChunks: (id) => {
              console.log('id: ', id);

              if (id.includes('node_modules')) {
                return 'vendor';
              }
            }
          }
        }
      },
})

image.png

gzip 压缩

插件:vite-plugin-compression2,vite-plugin-compression2(不维护)

cdn 加速

插件:vite-plugin-cdn-import