【uniapp】小程序支持分包存放微信自定义组件 wxcomponents

53 阅读2分钟

问题

在小程序端,不少开发者都有使用小程序原生自定义组件的需求,uniapp 也是支持使用小程序自定义组件的,只不过要放在根目录的 wxcomponents、mycomponents 等下面,详见官方文档

但是,在 5.03 之前,uniapp 仅支持在根目录存放自定义组件,很多开发者面临着包体积超出的问题

image.png

5.03 起,uniapp 开始支持在分包的根目录添加 wxcomponents、mycomponents 等

源码

此部分为源码分析,感兴趣的掘友可以看下

uniapp 仓库 中,支持的每一个小程序都有一个专门的包

image.png

复制操作是通过内部的 vite 插件实现的,具体位置在 packages/uni-cli-shared/src/vite/plugins/copy.ts,感兴趣的掘友可以看下。

框架已经封装好了复制的插件,对于各端来说,只需要做好配置就行。我们是要支持分包能复制 wxcomponents、mycomponents,这看起来就很简单了,只需要处理好分包的路径就行,代码比较简单,直接贴出来了

/**
 * 在将小程序组件相关资源(例如固定目录名下的静态文件)复制到构建产物时,
 * 生成本次复制所需的目录路径与 glob 模式列表。
 *
 * 返回值始终包含:
 * - 项目根(相对复制根目录)下名为 `dir` 的目录。
 * - 每个 `uni_modules` 插件包下对应子目录的 glob:与本函数内局部变量 `uniModulesDir` 相同
 *   (前缀为 `uni_modules`、通配段、`dir`、以及递归匹配尾部)。
 *
 * 当已设置 `UNI_INPUT_DIR`、`UNI_PLATFORM`,且输入目录下存在 `pages.json` 时,会从
 * `subPackages` 或 `subpackages` 读取分包根路径;对每个 `root` 再追加两项:
 * `normalizePath(path.join(root, dir))` 与 `normalizePath(path.join(root, uniModulesDir))`。
 *
 * 若缺少环境变量或不存在 `pages.json`,则只返回上述项目根级别的两项。
 *
 * @param dir - 资源目录名称(例如 `wxcomponents`)
 * @returns 非空数组,元素为规范化后的路径或 glob 字符串,供复制或监听工具使用。
 */
export function createCopyComponentDirs(dir: string) {
  const dirs = [dir]
  const uniModulesDir = 'uni_modules/*/' + dir + '/**/*'
  dirs.push(uniModulesDir)
  const inputDir = process.env.UNI_INPUT_DIR
  const platform = process.env.UNI_PLATFORM
  if (!inputDir || !platform) {
    return dirs
  }
  const pagesJsonFile = path.resolve(normalizePath(inputDir), 'pages.json')
  if (!fs.existsSync(pagesJsonFile)) {
    return dirs
  }
  const { appJson } = parseMiniProgramPagesJson(
    fs.readFileSync(pagesJsonFile, 'utf8'),
    platform,
    { subpackages: true }
  )
  const roots: string[] = Object.values(
    appJson.subPackages || appJson.subpackages || {}
  )
    .map(({ root }) => root)
    .filter(Boolean)
  roots.forEach((root) => {
    dirs.push(
      normalizePath(path.join(root, dir)),
      normalizePath(path.join(root, uniModulesDir))
    )
  })
  return dirs
}

注意事项

wxcomponents、mycomponents 等目录下方文件的处理是 全部拷贝到产物中,没有 treeShaking,因为需要开发者梳理组件的使用和存放。

交流群

我建了一个微信群(非官方),大家可以在群里和我沟通交流 uniapp 开发遇到的问题、uniapp 的源码等问题。

mmqrcode1774407130592.png