Vite 打包项目(二) : 打包一个支持按需引用的工具库

3,320 阅读1分钟

需求

最近有一个基建类库,是需要这个库可以按需引用或全量引用。原因在于这个库里面会同时使用在PC、小程序的环境,因此需要依赖由宿主包提供,同时避免包体积过大

Vite 库模式的缺陷

Vite 本身有 build.lib 配置项,其支持配置一个入口,入口项 entrystring 类型。从文档看,Vite 默认打包是全量打包,只有一个入口文件,里面需要引用类库的所有源码。Vite 会解析入口文件并压缩

根据官方文档,Vite 使用 Rollup 打包你的代码,并且它是预配置的。可以通过 rollupOptions 进行配置,其支持多入口文件配置

// 以下示例仅供参考
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

const path = require('path')

// 解决node-fs读取文件夹效率低问题
const fg = require('fast-glob')

const outDir = path.resolve(__dirname, 'lib')

const rollupOptions = {
  input: {},
  output: {
    globals: {
      react: 'React',
    },
  },
  // 确保外部化处理那些你不想打包进库的依赖
  external: [],
}

const genEntries = async () => {
  const entries = fg.sync(`src/**/*.*`, {
    onlyFiles: false,
    deep: Infinity,
  })

  entries.forEach((entry: string) => {
    const FILE_TYPE_SUFFIX_REG = /\.[t|j]s?$/g
    const TEST_FILE_REG = /__tests__/g

    if (FILE_TYPE_SUFFIX_REG.test(entry) && !TEST_FILE_REG.test(entry)) {
      const fileOutDir = entry.replace(FILE_TYPE_SUFFIX_REG, '')
      rollupOptions.input = {
        ...rollupOptions.input,
        [fileOutDir]: entry,
      }
    }
  })
}

genEntries()

Vite 构建配置开启库模式,同时将引入之前的 rollupOptions,实现多入口构建

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },

  json: {
    // 是否支持从 .json 文件中进行按名导入
    namedExports: true,
    // 若设置为 true, 导入的 JSON 会被转换为 export default JSON.parse("...") 会比转译成对象字面量性能更好
    // 尤其是当 JSON 文件较大时
    // 开启此项, 则会禁用按名导入
    stringify: false,
  },

  build: {
    outDir,
    lib: {
      // 使用 rollup 多入口构建,lib 模式 entry 字段为空即可
      entry: '',
      fileName: format => `${format}/[name].js`,
      formats: ['cjs', 'es'],
    },
    manifest: false,
    rollupOptions,
    commonjsOptions: {},
    emptyOutDir: true,
    // chunk 大小警告的限制
    chunkSizeWarningLimit: 500,
  },
})

node-fs 多层级读取文件的弊端

自带的 node-fs 循环或递归读取文件带来以下问题。node-fs 文件夹层级太深读取文件效率低,虽然类库的目录结构比较简单,但是有可能会出现嵌套文件夹

使用 fast-glob 替代 node-fs 读取文件

fast-glob It's a very fast and efficient glob library for Node.js.

参考文档

Vite.js中文官方文档
Rollup.js官方文档
fast-glob