uniapp微信插件动态注入分包

1. 概述

在微信小程序开发过程中,有时我们需要在小程序中集成第三方的一些特定的功能,这些功能以微信插件的形式存在。

对于使用第三方平台开发模式,对应的客户小程序非常多,每个客户引入的插件对于其他客户是不需要的,如果不同的客户的第三方小程序插件都集成在项目中,会非常影响包的大小。

本文采用一种在构建时动态插入分包插件的方式,实现对不同客户的微信插件动态加载与使用。下面介绍下整体使用和构建时动态引入过程。

2. 微信插件的使用方式

2.1 添加插件

在使用插件前,首先要在小程序管理后台的"设置-第三方服务-插件管理"中添加插件。开发者可登录小程序管理后台,通过 appid 查找插件并添加。

如果插件无需申请,添加后可直接使用;否则需要申请并等待插件开发者通过后,方可在小程序中使用相应的插件。

2.2 引入插件代码包

微信插件有两种引入方式:

  • 第一种是全局引入
  • 第二种是分包引入

2.2.1 全局引入

manifest.json中的各平台对应的字段内声明使用的插件:

json 复制代码
// 微信小程序
"mp-weixin": {
  "plugins": {
    "myPlugin": {
      "version": "1.0.0",
      "provider": "wxidxxxxxxxxxxxxxxxx",
      "export": "index.js"
    }
  }
}

// 支付宝小程序
"mp-alipay": {
  "plugins": {
    "myPlugin": {
      "version": "*",
      "provider": "2019235609092837",
      "export": "index.js"
    }
  }
}

页面中使用

json 复制代码
// 微信小程序
{
  "path": "pages/index/index",
  "style": {
    "mp-weixin": {
      "usingComponents": {
        "hello-component": "plugin://myPlugin/hello-component"
      }
    }
  }
}

// 支付宝小程序
{
  "path": "pages/index/index",
  "style": {
    "mp-alipay": {
      "usingComponents": {
        "hello-component": "plugin://myPlugin/hello-component"
      }
    }
  }
}

2.2.2 分包引入

支付宝小程序、百度小程序不支持在分包内引入插件。仅针对微信小程序。

如果插件只在(同一个插件不能被多个分包同时引用)一个分包用到,可以单独配置到分包中,这样插件不会随主包加载,开发者可以在pages.jsonsubPackages中声明插件。

json 复制代码
"subPackages": [{
    "root": "pagesA",
    "pages": [{
        "path": "list/list"
    }]
    "plugins": {
        "pluginName": {
            "version": "1.0.0",
            "provider": "wxidxxxxxxxxxxxxxxxx"
        }
    }
}]

3. 动态添加分包插件实现

因为不同的小程序需要的插件不一样,需要进行动态选择打包编译,以减少构建的体积。

下面介绍下整体的实现过程:

3.1 第一步:分包插件配置文件

json 复制代码
{
  "WRD": {
    "subPackage": "pagesD",
    "plugins": {
      "plugtest": {
        "version": "2.0.4",
        "provider": ""
      }
    }
  },
  "studentVerify": {
    "subPackage": "pagesA",
    "plugins": {
      "plugtest": {
        "version": "latest",
        "provider": ""
      }
    }
  }
}

配置成json文件,可以一个分包可以配置多个插件,比如对应的WRD提供给构建使用。

3.2 第二步:替换脚本呢

主要通过正则找到分包中的位置,在pages.json对应分包下添加插件。

javascript 复制代码
const fs = require('fs');
const path = require('path');

// 读取文件内容
function readFile(filePath) {
    return fs.readFileSync(filePath, 'utf-8');
}

// 写入文件
function writeFile(filePath, data) {
    fs.writeFileSync(filePath, data, 'utf-8');
}

// 检查插件是否已存在
function isPluginExists(pagesData, pluginKey) {
    const pluginCheckRegex = new RegExp(`"plugins":\s*\{[^}]*"${pluginKey}":`, 's');
    return pluginCheckRegex.test(pagesData);
}

// 添加插件
function addPluginToSubPackage(pagesData, pluginEntry) {
    const subPackageName = pluginEntry.subPackage;
    const pluginKey = Object.keys(pluginEntry.plugins)[0]; // 假设只处理一个插件

    // 找到对应的 subPackage
    const subPackageRegex = new RegExp(`(\{\s*"root":\s*"${subPackageName}",\s*)`, 's');
    const match = pagesData.match(subPackageRegex);

    if (match) {
        // 检查特定插件是否已存在
        if (isPluginExists(pagesData, pluginKey)) {
            console.log(`插件 "${pluginKey}" 在 "${subPackageName}" 已经存在.`);
            return null;  // 不进行修改
        }

        // 构建新插件字符串
        const newPlugins = `  "plugins": ${JSON.stringify(pluginEntry.plugins, null, 2)},\n`;

        // 将新插件字符串添加在 root 后,并确保后面还有 pages 数组
        return pagesData.replace(subPackageRegex, `${match[1]}${newPlugins}`);
    } else {
        console.error(`分包 "${subPackageName}" 不存在.`);
        return null;
    }
}

// 主函数
function main(pluginKey) {
    const pagesFilePath = path.join(__dirname, '../src', 'pages.json');
    const pluginMapFilePath = path.join(__dirname, '../src', 'jsonEnv', 'pluginMap.json');

    const pagesData = readFile(pagesFilePath);
    const pluginMap = JSON.parse(readFile(pluginMapFilePath));

    if (!pluginMap[pluginKey]) {
        console.error(`插件值 "${pluginKey}" 没有定义在pluginMap中.`);
        return;
    }

    const pluginEntry = pluginMap[pluginKey];
    const updatedData = addPluginToSubPackage(pagesData, pluginEntry);

    if (updatedData) {
        writeFile(pagesFilePath, updatedData);
        console.log(`插件 "${pluginKey}" 添加到pages.json的 "${pluginEntry.subPackage}"中.`);
    }
}

// 运行脚本
const pluginKey = process.argv[2];
if (!pluginKey) {
    console.error('请提供插件参数值');
    process.exit(1);
}

main(pluginKey);

具体流程是:

  1. 通过node addPlugin.js WRD, 读取 pluginMap.jsonpages.json 文件。

    1. pluginMap.json 文件包含了所有的插件定义,每个插件有对应的 subPackageplugins 信息。 pages.json 是存储分包配置信息的文件,其中包含多个分包,每个分包可能包含不同的插件。
  2. 检查插件是否已存在

    1. 在处理每个插件时,首先会检查目标分包(subPackage)中是否已经存在该插件。此时,我们会遍历 pages.json 文件,使用正则表达式检查 plugins 部分,看看是否已经定义了该插件。如果插件已存在,就跳过添加步骤,避免重复插入。如果插件不存在,则继续添加。
  3. 查找定位

    1. 根据 pluginMap.json 中的 subPackage 字段,查找 pages.json 文件中对应的分包。每个分包是一个包含多个字段的对象,其中 root 字段会定义该分包的根目录。通过正则表达式匹配分包中的 root 字段,确保我们定位到正确的分包。
  4. 修改 pages.json 文件

    1. 当找到对应的分包时,我们会添加插件到该分包的 plugins 部分。构造一个新的 plugins 字段,将插件数据以 JSON 格式插入。如果插件已经存在,跳过该操作。

3.3 第三步:jenkins配置

这一步,需要在jenkins中配置下拉选项,提供给构建使用:

运行提示:

4. 总结

最后总结一下:在引入插件开发中,动态添加插件可以针对不同客户的定制化插件加载,减小包体积。通过定义插件的分包和版本信息,在构建时使用脚本动态修改 pages.json 文件,避免重复添加插件并确保各分包只加载所需插件。

如有错误,请指正O^O!

相关推荐
sunshine64120 分钟前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻43 分钟前
Vue(四)
前端·javascript·vue.js
蜜獾云1 小时前
npm淘宝镜像
前端·npm·node.js
dz88i81 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr1 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
顾平安2 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网2 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工2 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
不是鱼2 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos