uniApp小程序改造插件筆記-分包插件調(diào)研

概述:

分包速度快登颓,第一版穩(wěn)定性較強,后臺修改較少红氯,需要主包配合一些配置框咙,但后期可能每次都需要主包進行一些配合咕痛。 (速度型,類似sdk)
插件修改內(nèi)容較多喇嘱,開發(fā)速度較慢茉贡,第一版相對不穩(wěn)定,后臺配合修改較多者铜,也需要主包進行一點配置块仆,暫不支持手機號獲取等部分API,但后期操作可能更加獨立王暗,更適合其它小程序?qū)印#ㄩL遠型)

  • 注意:2.12.2基礎(chǔ)庫后插件頁就可以調(diào)小程序組件了庄敛,也就是可以實現(xiàn)手機號俗壹、用戶信息獲取功能而無需功能頁,但是只能小程序組件只能在插件頁使用藻烤,不能在插件的組件中使用绷雏。
插件不能使用及處理:
  • getApp() ===> getApp()替換成處理vue 的store
  • 獲取用戶信息、手機號 ===> 用戶功能頁/2.12.2基礎(chǔ)庫調(diào)小程序組件(僅插件頁)
  • 其它Api ===> 可通過小程序提供方法 給插件怖亭,插件回調(diào)小程序方法 間接調(diào)取微信Api (js 中重寫Api方法)
  • ext.json ===> 需通過將插件ext.json合并到小程序ext.json中通過插件回調(diào)小程序提供方法方式間接獲取
  • 路由 ===> navigateTo url處理涎显,底層磨平使用plugin-private://wxXXXXXXXX+url 跳轉(zhuǎn)

tips: 外部直接跳會員中心小程序頁面:(_plugin_/wxXXXXXXXX+url)

插件改造步驟

嵌套模式開發(fā) : 一套代碼,子目錄為小程序目錄兴猩,外層目錄為插件殼目錄期吓。從而實現(xiàn)一套代碼開發(fā)插件與小程序,小程序從小程序目錄運行倾芝,插件通過外殼編譯后使用微信開發(fā)者工具運行讨勤。

插件判斷頁面中可以通過方法(getCurrentPages..pop().route中是否包含plugin/Appid )判斷是否是插件
非頁面中不能判斷是否是插件

插件開發(fā)策略:盡量通過全局處理方式進行處理,避免過多的差異開發(fā)

改造流程:
->首先:git新增分支插件+小程序dev作為日后開發(fā)分支晨另。
->分支集成添加vue-cli
->安裝uniapp2wxpack
->將小程序項目配置到src中
->修改插件測試主程序內(nèi)容(pluginActions.js潭千、functionalPages、插件引入借尿、跳轉(zhuǎn)插件鏈接)
(注意:主程序可通過pluginActions.js 提供接口方法刨晴、變量給插件,插件通過plugin.json可提供組件路翻、頁面狈癞、接口js給主程序。)
->插件跳轉(zhuǎn)鏈接:plugin://插件名/插件頁名或 plugin-private://wxXXXXXXXX/+url茂契,一般用第一種亿驾,因為不對外暴露頁面路徑

npm run dev:mp-weixin-pack-plugin (開發(fā)模式) 方便調(diào)試
npm run build:mp-weixin-pack-plugin (生產(chǎn)模式)打出的包小

相關(guān)命令:
-> npx uniapp2wxpack --create (安裝uniapp2wxpack)
-> npm run dev:mp-weixin-pack-plugin (打包)

開發(fā)優(yōu)化:

切換小程序/插件開發(fā)需要在項目src目錄下手動執(zhí)行build.js 重新生成pages.json, 通過pages-gaps.json文件配置小程序與插件在pages.json中的差異點
-> 執(zhí)行 “ node ./build.js app “或“ node ./build.js “生成 小程序 pages.json
-> 執(zhí)行 node ./build.js plugin 生成 插件 pages.json

如果使用全局變量切換項目是否是插件可重寫main.js添加MP_Plugin字段實現(xiàn)

build文件內(nèi)容

/*
    處理pages.json內(nèi)容插件/小程序差異
    -> cd 到build.js 所在目錄
    -> 執(zhí)行 “ node ./build.js app “或“ node ./build.js “生成 小程序 pages.json
    -> 執(zhí)行 node ./build.js plugin 生成 插件 pages.json
*/

const fs = require('fs')
var arguments = process.argv.splice(2);

/* pages.json */
// 讀
let pagesJson = fs.readFileSync(__dirname + '/pages.json','utf8')
let gapsJson = fs.readFileSync(__dirname + '/pages-gaps.json','utf8')

// 改
pagesJson = JSON.parse(pagesJson);
gapsJson = JSON.parse(gapsJson);
if(arguments.length>0){
    if ((typeof pagesJson) === "object") {
        findGaps(pagesJson,arguments[0])
    }
}

function findGaps(obj,type){
    for(let key in obj){
        let item = obj[key];
        if ((typeof item) === "object") {
            if (item.gaps_key && item.gaps_title) { // 找到差異點
                changeGaps(item,type)
            }
            findGaps(item,type)
        } 
    }
}

function changeGaps(obj,type){
    let change = "";    
    if (type == 'plugin') { // 插件
        if(gapsJson.plugin[obj.gaps_key]){
            change = gapsJson.plugin[obj.gaps_key]
        }
    } else { // 小程序
        if(gapsJson.app[obj.gaps_key]){
            change = gapsJson.app[obj.gaps_key]
        }
    }
    obj[obj.gaps_title] = change;
}

// 寫
fs.writeFile(
 __dirname + '/pages.json',
 // 我這邊是用兩個空格來縮進 pages.json账嚎,如果喜歡制表符莫瞬,第三個參數(shù)更換你為 \t 即可
 JSON.stringify(pagesJson, null, '\t'),
 e => e ? console.error(e) : console.log('pages.json 配置文件更新成功')
)


/* main.js */
let mainJs = fs.readFileSync(__dirname + '/main.js','utf8')
if(arguments.length>0){
    let strA = "import Vue from 'vue'\nVue.prototype.MP_Plugin = true;\n";
    let strB = "import Vue from 'vue'\nVue.prototype.MP_Plugin = false;\n";
    if (arguments[0] == 'plugin') { // 插件
        changeMP_Plugin(strA, strB);
    } else { // 小程序
        changeMP_Plugin(strB,strA);
    }
}

function changeMP_Plugin(newStr,oldStr){
    if(mainJs.indexOf(newStr) > -1){ // 不用修改
        return;
    }   
    if(mainJs.indexOf(oldStr) > -1){
        var reg= new RegExp(oldStr,"g"); 
        mainJs = mainJs.replace(reg,newStr)
    } else {
        if(mainJs.indexOf("import Vue from 'vue'") > -1){
            var reg= new RegExp("import Vue from 'vue'","g");
            mainJs = mainJs.replace(reg,newStr)
        }else{
            console.log("未找到import Vue from 'vue'")
        }
        
    }
}

fs.writeFile(
 __dirname + '/main.js',
 // 我這邊是用兩個空格來縮進 main.js儡蔓,如果喜歡制表符,第三個參數(shù)更換你為 \t 即可
 mainJs,
 e => e ? console.error(e) : console.log('main.js 配置文件更新成功')
)

pages-gaps.json文件內(nèi)容:
mini-program-plug-xxx-comp: 插件中使用小程序的組件

{
    "http://"  : "差異json配置說明: 在pages.json 中有差異地方添加屬性gaps_key和gaps_title( \"gaps_key\": \"gaps_xxx\",\"gaps_title\": \"yyy\" 疼邀,在此文件中寫差異配置喂江,key 為gaps_key定義的值)",
    "app" : {
        "gaps_home_style":{
            "enablePullDownRefresh": true,
            "mp-weixin": {
                "usingComponents": {
                    "cell":     "plugin://contactPlugin/cell"
                }
            }
        }
    },
    "plugin" : {
        "gaps_home_style":{
            "enablePullDownRefresh": true,
            "componentGenerics":{
                "mini-program-plug-xxx-comp":true
            }
        }
    }
}

總括

src添加文件:
build.js : 用來執(zhí)行生成pages.json ,從插件開發(fā)切換到小程序開發(fā)或從小程序開發(fā)切換到插件開發(fā)時使用,命令node ./build.js plugin
pages-gaps.json: 配置pages.json中插件與小程序差異內(nèi)容文件
plugin-fit.js: 底層磨平插件與小程序差異內(nèi)容(api調(diào)用旁振,方法等)

主程序添加文件:
pluginActions.js : 主程序供插件調(diào)用api方法
ext.json : 插件ext配置文件(合并主程序中)
plug-xxx-comp組件: 外部組件供插件使用(處理插件一些無法調(diào)用的組件)
app.json配置:

    "plugins" : {
            "xxx" : {
                "version" : “1.0.0”,
                "provider" : "wxXXXXXXXXXX",
                "export" : "pluginActions.js",
                "genericsImplementation": {
                    "xxx-home": {
                      "mini-program-plug-xxx-comp": "component/plug-xxx-comp/plug-xxx-comp"
                    }
                }
                     }
         },
           "functionalPages" : {
               "independent" : true
           },
           "permission": {
             "scope.userLocation": {
               "desc": "根據(jù)位置進行定位"
             }
         }

tips:主包使用不了分包的組件获询,分包可以使用主包的組件

底層磨平文件plugin-fit.js內(nèi)容:


/* 
    插件處理 
*/
import Vue from 'vue'
// Api
uni.getExtConfigSync = function() {
    return actionApi("getExtConfigSync")
}

uni.authorize = function(params) {
    console.log('authorize');
    return actionApi("authorize",params)
}

wx.addCard = function(params){
    return actionApi("addCard",params);
}


uni.clearStorageSync = function(params) {
    return actionApi("clearStorageSync",params)
}

uni.hideKeyboard = function() {
    return actionApi("hideKeyboard")
}

uni.saveFile = function(params) {
    return actionApi("saveFile",params)
}

uni.getSavedFileList = function(params) {
    return actionApi("getSavedFileList",params)
}

uni.checkSession = function(params) {
    return actionApi("checkSession",params)
}

uni.login = function(params) {
    return actionApi("login",params)
}

uni.getUserInfo = function(params) {
    return actionApi("getUserInfo",params)
}

// 插件小程序跳轉(zhuǎn) 如果是本地則直接返回
uni.navigateToMiniProgram = function(params) {
    if (params["appId"] == uni.getAccountInfoSync().miniProgram.appId) {
        return uni.navigateBack({
            delta:1000,
        });
    }
    return actionApi('navigateToMiniProgram', params);
}

uni.getAccountInfoSync = function(){
    return actionApi("getAccountInfoSync");
}




// route
const pluginUrlHead = "plugin-private://wxXXXXXXXXXX";

defineRoute ('navigateTo')
defineRoute ('switchTab')
defineRoute ('reLaunch')
defineRoute ('redirectTo')
 
var unit = require("@/common/unit/unit.js");
function defineRoute(name) {
    const originRoute = uni[name];
    Object.defineProperty(uni, name, {
        configurable: true,
        enumerable: true,
        writable: true,
        value: function (obj) {
            if (!Vue.prototype.MP_Plugin) {
                return originRoute(obj);
            }
            if(obj.url.indexOf('/xxxxx')>-1){
                let mall_appid = unit.getMallAppid();
                let mall_path = unit.getMallAppPath();
                console.log(mall_appid)
                uni.navigateToMiniProgram({
                  appId: mall_appid,
                  path: mall_path,
                  success(res) {
                  },
                  fail(err) {
                  }
                })
                return;
            }
            console.log("url",obj);
            var newurl = pluginUrlHead + obj.url;
            if(obj.miniProgram_page){
                return originRoute({
                    url:obj.url
                });
            }else{
                return originRoute({
                    url:newurl
                });
            }
        }
    })
}

// Storage 存儲 
const getStorageSync = uni.getStorageSync;
uni.getStorageSync = function(key) {
    if(Vue.prototype.MP_Plugin && key == 'userInfo'){ 
        return requireMiniProgram().getMemberUserinfo();
    }
    return getStorageSync(key);
}

/** 
 *  api調(diào)用
 *  apiName api 名稱
 *  params 參數(shù)
*/
function actionApi(apiName,params) {
    let originApi = null;
    // #ifdef MP-WEIXIN
        originApi = wx[apiName];
    // #endif
    // #ifndef MP-WEIXIN
        originApi = uni[apiName];
    // #endif
    if (!Vue.prototype.MP_Plugin) { // 小程序還執(zhí)行原始api
        return originApi(params);
    }
    return requireMiniProgram().xxxPublic(apiName, params);
}

pluginActions.js文件內(nèi)容

module.exports = { 
    //名稱 需要 xxxPublic 
      xxxPublic(funName, param) {
          return wx[funName](param);
      },
      getMemberUserinfo(){
            return wx.getStorageSync('userInfo');   
      }
}

========================================================================================================================

小程序使用插件修改內(nèi)容:

1.app.json

    "subPackages": [
        {
            "root": "pages/xxx/",
            "pages": [
                {
                    "http://": "授權(quán)頁",
                    "path": "plugin-auth",
                    "style": {}
                }
            ],
            "plugins": {
                "xxx": {
                    "version": "1.0.0",
                    "provider": "wxXXXXXXXXXX",
                    "export": "pluginActions.js",
                    "genericsImplementation": {
                        "xxx-home": {
                            "mini-program-plug-xxx-comp": "component/plug-xxx-comp/plug-xxx-comp"
                        }
                    }
                },
                "contactPlugin": {
                    "version": "1.3.0",
                    "provider": "wx104a1a20c3f81ec2"
                    }
            },
            "functionalPages": {
                "independent": true
            },
            "permission": {
                "scope.userLocation": {
                    "desc": "根據(jù)位置進行定位"
                }
            }
        }
    ]
  1. 單獨文件夾添加 plugin-auth 授權(quán)頁、pluginActions.js拐袜、plug-xxx-comp
    3.ext中添加內(nèi)容
    "ext": {
        "version": "1.0",
        "api_url": "https://x x x/", // 插件網(wǎng)絡(luò)請求地址
        "mall_appid": "",     // 其它小程序id吉嚣,沒有“”即可
        "mall_path": ""     // 其它小程序path,沒有“”即可
      },

4.需要跳轉(zhuǎn)插件的地方直接跳轉(zhuǎn)授權(quán)頁就行蹬铺,授權(quán)頁已授權(quán)會直接跳插件尝哆,未授權(quán)會展示授權(quán)頁內(nèi)容

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市甜攀,隨后出現(xiàn)的幾起案子秋泄,更是在濱河造成了極大的恐慌,老刑警劉巖规阀,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恒序,死亡現(xiàn)場離奇詭異,居然都是意外死亡谁撼,警方通過查閱死者的電腦和手機歧胁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厉碟,“玉大人与帆,你說我怎么就攤上這事∧” “怎么了玄糟?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袄秩。 經(jīng)常有香客問我阵翎,道長,這世上最難降的妖魔是什么之剧? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任郭卫,我火速辦了婚禮,結(jié)果婚禮上背稼,老公的妹妹穿的比我還像新娘贰军。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布词疼。 她就那樣靜靜地躺著俯树,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贰盗。 梳的紋絲不亂的頭發(fā)上许饿,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天,我揣著相機與錄音舵盈,去河邊找鬼陋率。 笑死,一個胖子當著我的面吹牛秽晚,可吹牛的內(nèi)容都是我干的瓦糟。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼赴蝇,長吁一口氣:“原來是場噩夢啊……” “哼菩浙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扯再,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎址遇,沒想到半個月后熄阻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡倔约,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年秃殉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浸剩。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡钾军,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绢要,到底是詐尸還是另有隱情吏恭,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布重罪,位于F島的核電站樱哼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏剿配。R本人自食惡果不足惜搅幅,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呼胚。 院中可真熱鬧茄唐,春花似錦、人聲如沸蝇更。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至漾抬,卻和暖如春宿亡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纳令。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工挽荠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人平绩。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓圈匆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捏雌。 傳聞我的和親對象是個殘疾皇子跃赚,可洞房花燭夜當晚...
    茶點故事閱讀 45,982評論 2 361