使用gulp对微信小游戏进行分包

方案

  1. 生成未压缩混淆的游戏整包 wxgame.js
  2. 截取中间部分标记切割wxgame.js为两个wxgame.js
  3. 把依赖包含到window上

示例

gulp task配置


/**
 * 编译成单个js  不创建 window.a =a ;
 * 
 * @param {*} fileName 生成的名字
 * @param {*} outPath 输出路径
 * @returns
 */
function compileWXTSFile(outPath, fileName) {
    // 混淆参数
    const uglifyOptions = {
        mangle: true,// 混淆
        compress: false // 不压缩
    }
    return gulp.src([
        "libs/*.ts",
        "src/**/*.ts"
    ])
        .pipe(sorter(false)) // 排序  false 不显示日志
        .pipe(tsProj()) // 编译TS文件
        .pipe(concat(fileName)) // 合并编译后的js到一个文件
        .pipe(gulp.dest(outPath))
}

/**
 *  筛选出 window.a=a 生成独立js  
 */
function createWXExport() {
    // 进行编译 不进行混淆
    return gulp.src([
        "libs/*.ts",
        "src/**/*.ts"
    ])
        .pipe(sorter(false)) // 排序  false 不显示日志
        .pipe(tsProj()) // 编译TS文件 // 读取已经混淆好的整包
        .pipe(wxTools(true)) //  筛选顶层引用 用 window.a = a 包含
        .pipe(concat("wxgame_export.js"))
        .pipe(gulp.dest("wxgame_out/"))
}


/**
 * 添加  window.a=a 到尾部
 * @param { } inFile 
 * @param {*} outPath 
 * @param {*} outFileName 
 */
var conactExport = function (inPath, outPath, fileName) {
    return gulp.src([
        inPath + fileName,
        gameJSExport,
    ])
        .pipe(concat(fileName))
        .pipe(gulp.dest(outPath))
        .on("end", () => {
            console.log("sub success =>> ", outPath, fileName)
        })
}


/**
 *  分包
 * @param {string } path  切割后输出路径
 * @param {string} fileName  生成文件名
 * @param {boolean} isLast 
 * @param {string } head 
 */
function subWX(tempPath, outPath, fileName, isLast, head) {
    var key = `define("game/battle/control/BattleDataControl"`
    var uglifyArgs = {
        mangle: false, // 分包不再进行混淆 只压缩空白
        compress: {}
    }

    return gulp.src([gameJS,])
        .pipe(wxSub(key, isLast, head))
        .pipe(wxTools()) //  筛选顶层引用 用 window.a = a 包含
        .pipe(concat(fileName))
        // .pipe(uglify(uglifyArgs)) //打开则进行混淆这里方便调试
        .pipe(gulp.dest(tempPath))
        .on("end", () => { // 结束后
            return conactExport(tempPath, outPath, fileName);
        })
}


// 微信分包
gulp.task('wxsub', function (args, args2) {

    var head = `var Laya = window.Laya;\n`;
    var head2 = `  var Laya = window.Laya;var __extends = window.__extends;\n`;
    // 编译
    if (compile && compile.c != null) {
        console.log("start wx compile");
        return compileWXTSFile("wxgame_out", "wxgame.js").on("end", () => {
            console.log("compileWXTSFile Finish");
            createWXExport().on("end", () => {
                subWX("wxgame_out/sub1/", "wxgame/sub1/", "wxgame.js", false, head);
                subWX("wxgame_out/sub2/", "wxgame/sub2/", "wxgame.js", true, head2);
            })
        })
    } else {
       // 不编译 直接拿已经编译的进行切割
        subWX("wxgame_out/sub1/", "wxgame/sub1/", "wxgame.js", false, head);
        subWX("wxgame_out/sub2/", "wxgame/sub2/", "wxgame.js", true, head2);
    }

});

gulp 插件

根据key截取代码

'use strict';

var through = require('through2');
var path = require('path');
var File = require('vinyl');
var Concat = require('concat-with-sourcemaps');
var gutil = require('gulp-util');
var PluginError = gutil.PluginError;

/**
 *  微信分包工具 ,基于amd模式下开发的游戏
 *  将 var  XXX 包装到 window.XXX =XXX;
 * @param key 分包关键位置
 * @param   isLast  是否是取后面的
 * @param isMain  是否是主包 主包不分包 但是加头部
 */
var wxgameSubTools = function (key, isLast, head, isMain) {

    function onFile(file, enc, cb) {
        if (file.isStream()) {
            console.error('Streams are not supported!');
            return cb();
        }
        let contents = "" + file.contents;
        let outStr;

        if (!isMain) {
            if (key == null || key == "") {
                console.error("key ", 'key= ' + key);
                return cb();
            }
            const index = contents.indexOf(key);
            if (index == -1) {
                console.error('not find key ! key= ' + key);
                return cb();
            }
            if (!isLast) { // 
                outStr = contents.substr(0, contents.indexOf(key));
            } else {
                outStr = contents.substr(contents.indexOf(key));
            }
        }else{
            outStr = contents;
        }
        // 头部添加的文本
        if (head) {
            outStr = head + outStr;
        }
        file.contents = new Buffer(outStr);
        cb();
        this.emit("data", file);
    }
    // 不处理end 使用默认的end
    return through.obj(onFile);
};

module.exports = wxgameSubTools;

生成分包 ,提取依赖到window

'use strict';

var through = require('through2');
var path = require('path');
var File = require('vinyl');
var Concat = require('concat-with-sourcemaps');

/**
 *  微信分包工具 ,基于amd模式下开发的游戏
 *  将 var  XXX 包装到 window.XXX =XXX;
 * @param {boolean } isExport  是否是只输出window.a=a
 */
var wxgameTools = function (isExport) {

    /**
     * 流处理  匹配 /(?:^|\n)(function|var) [_0-9a-zA-Z]+/ig; 添加为 window.XXX = XXX;
     *
     * @param {*} file 流文件 
     * @returns
     */
    function onFile(file, enc, cb) {
        if (file.isStream()) {
            this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!'));
            return cb();
        }

        var contents = "" + file.contents;
        // 匹配fuanction XXX   或者 var XXX 
        var reg = /(?:^|\n)(function|var) [_0-9a-zA-Z]+/ig;
        // 匹配fuanction   或者 var  去掉 function 或者 var 
        var reg2 = /(?:^|\n)(function|var) /ig;
        var match = contents.match(reg)
        if (match && match.length > 0) {
            var strs = ""
            for (var i = 0; i < match.length; i++) {
                var str = match[i].replace(reg2, "");
                strs += "\n try{window." + str + "=" + str + ";}catch(e){console.warn("+'"'+str+'")}';
            }
            var bf = new Buffer( strs ); // 提前分配
            if(isExport){
                file.contents = bf;
            }else{
                file.contents = Buffer.concat([file.contents, bf])
            }
            
        }
        cb();
        this.emit("data",file);
    }
    // 不处理end 使用默认的end
    return through.obj(onFile);
};

module.exports = wxgameTools;
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容