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.json
的subPackages中声明插件。
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);
具体流程是:
-
通过
node addPlugin.js WRD
, 读取pluginMap.json
和pages.json
文件。pluginMap.json
文件包含了所有的插件定义,每个插件有对应的subPackage
和plugins
信息。pages.json
是存储分包配置信息的文件,其中包含多个分包,每个分包可能包含不同的插件。
-
检查插件是否已存在
- 在处理每个插件时,首先会检查目标分包(
subPackage
)中是否已经存在该插件。此时,我们会遍历pages.json
文件,使用正则表达式检查plugins
部分,看看是否已经定义了该插件。如果插件已存在,就跳过添加步骤,避免重复插入。如果插件不存在,则继续添加。
- 在处理每个插件时,首先会检查目标分包(
-
查找定位
- 根据
pluginMap.json
中的subPackage
字段,查找pages.json
文件中对应的分包。每个分包是一个包含多个字段的对象,其中root
字段会定义该分包的根目录。通过正则表达式匹配分包中的root
字段,确保我们定位到正确的分包。
- 根据
-
修改
pages.json
文件- 当找到对应的分包时,我们会添加插件到该分包的
plugins
部分。构造一个新的plugins
字段,将插件数据以 JSON 格式插入。如果插件已经存在,跳过该操作。
- 当找到对应的分包时,我们会添加插件到该分包的
3.3 第三步:jenkins配置
这一步,需要在jenkins中配置下拉选项,提供给构建使用:
运行提示:
4. 总结
最后总结一下:在引入插件开发中,动态添加插件可以针对不同客户的定制化插件加载,减小包体积。通过定义插件的分包和版本信息,在构建时使用脚本动态修改 pages.json
文件,避免重复添加插件并确保各分包只加载所需插件。
如有错误,请指正O^O!