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!

相关推荐
刘志辉2 分钟前
react的创建与书写
前端·react.js·前端框架
我是苏苏3 分钟前
Web开发:ABP框架6——appsetting.json的读取以及实例的注入
前端·windows·json
秋雨凉人心6 分钟前
uniapp 设置安全区域
前端·javascript·vue.js·uni-app
柳问星37 分钟前
parallel-wait-run, 一个并行运行多个 npm scripts 的小工具
前端·javascript·npm
One_Blanks39 分钟前
网络安全-HTML基础
前端·安全·html
豆包MarsCode1 小时前
使用 Vue 配合豆包MarsCode 实现“小恐龙酷跑“小游戏
开发语言·前端·javascript·vue.js·html
四喜花露水1 小时前
vue2.x elementui 固定顶部、左侧菜单与面包屑,自适应 iframe 页面布局
前端·elementui·vue
看山还是山,看水还是。1 小时前
Redis 命令
前端·数据库·redis·bootstrap
会飞的郁金香1 小时前
第8章 利用CSS制作导航菜单
前端·css
凉风听雪1 小时前
免费HTML模板和CSS样式网站汇总
前端·javascript·css·html