阅读视图

发现新文章,点击刷新页面。

【uniapp】小程序实现自由控制组件JSON文件配置

前言

最近在 uniapp ask社区 回答问题,不少开发者都咨询到了如何配置 组件 生成的 json文件 这个问题,在经过跟同事的交流、自己的实践以及开发者的反馈后,我整理了下面的解决思路和方案。

前置知识

uniapp 编译到 小程序,一个 vue 组件编译结束之后会生成四个文件,以微信小程序举例

image.png

生成的 json文件 的内容存储着小程序页面或组件相关的配置,必不可少

方案一 脚本

这个思路是在框架打包结束之后通过 nodejs 或者 shell 去修改产物

以占位组件为例,做分包异步化降低主包体积不可或缺的一个配置项

image.png

开发者只需要事先统计好需要配置的 componentPlaceholder 和 产物路径,在打包结束之后通过脚本把内容写入到对应的 json文件 就可以了

这种思路适合 cli项目,可以很轻松把脚本添加到 package.json 中的 scripts 中,并且不受 nodejs 版本限制;但是有些开发者的项目是 hx项目,就不能通过脚本的形式来操作了。

方案二 插件

这个思路是通过 webpack 或者 vite 插件来解决相关问题

我们以我写的 vite 插件 为例 (github 地址 github.com/uni-toolkit…

插件源码很简单,五十多行代码

import { getOutputJsonPath, isMiniProgram } from '@uni_toolkit/shared';
import type { PluginOption } from 'vite';
import { createFilter, type FilterPattern } from '@rollup/pluginutils';
import path from 'node:path';
import fs from 'node:fs';
import { parseJson } from '@dcloudio/uni-cli-shared';
import { merge } from 'lodash-es';

export interface ComponentConfigPluginOptions {
  include?: FilterPattern;
  exclude?: FilterPattern;
}

export default function vitePluginComponentConfig(
  options: ComponentConfigPluginOptions = {
    include: ['**/*.{vue,nvue,uvue}'],
    exclude: [],
  },
): PluginOption {
  const map: Map<string, Record<string, any>> = new Map();
  return {
    name: 'vite-plugin-component-config',
    enforce: 'pre',
    transform(code, id) {
      if (!isMiniProgram()) {
        return;
      }
      if (!createFilter(options.include, options.exclude)(id)) {
        return;
      }
      const matches = code.match(/<component-config>([\s\S]*?)<\/component-config>/g);
      if (!matches) {
        return;
      }

      matches.forEach((match) => {
        const content = match.replace(/<component-config>|<\/component-config>/g, '');
        const componentConfig = parseJson(content.toString(), true, path.basename(id));
        map.set(getOutputJsonPath(id), componentConfig);
      });

      return code.replace(/<component-config>[\s\S]*?<\/component-config>/g, '');
    },
    closeBundle() {
      if (map.size === 0) {
        return;
      }
      for (const [outputPath, config] of map) {
        if (!fs.existsSync(outputPath)) {
          continue;
        }
        const content = fs.readFileSync(outputPath, 'utf-8');
        const json = JSON.parse(content);
        fs.writeFileSync(outputPath, JSON.stringify(merge(json, config), null, 2));
      }
    },
  };
}

思路就是需要开发者在具体的 vue文件 中添加一个 component-config 代码块,类如

// #ifdef MP
<component-config>
{
  "usingComponents": {
    "custom-button": "/components/custom-button"
  },
  "styleIsolation": "apply-shared",
  "componentPlaceholder": {  
    "test": "view",  
  }  
}
</component-config>
// #endif

在编译期间,会通过正则表达式提取 component-config 代码块中的配置,存储到 hashMap 中,在 bundle 生成结束后遍历 hashMap 中的数据,然后修改对应路径的 json文件

同时还考虑到有些开发者会针对不同的小程序平台添加不同的配置,component-config 代码块中的内容也支持 条件编译

如果你是 vue2 项目,可以使用这个插件 github 地址 github.com/uni-toolkit…

结语

如果这些插件帮助到了你,可以点个 star✨ 支持一下开源工作。

如果你有什么好的想法或者建议,欢迎在 github.com/uni-toolkit… 提 issue 或者 pr;也可以加我的 微信 13460036576 沟通。

❌