资讯专栏INFORMATION COLUMN

kmdjs集成uglifyjs2打造极致的编程体验

Pink / 2447人阅读

摘要:怎样才算更好不用依赖注入不用写,自动匹配依赖如下所示这就要借助能力,把的字符串替换成带有就可以实现上面的效果。再也不用区分循环依赖和非循环依赖了上面的所有代码可以上找到

回顾

上篇文章大概展示了kmdjs0.1.x时期的编程范式:
如下面所示,可以直接依赖注入到function里,

kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function(bom,Ball,test) {
    var ball = new Ball(0, 0, 28, 1, -2, "kmdjs");
    var vp = bom.getViewport();
});

也可以直接在代码里把full namespace加上来调用,如:

kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function() {
    var ball = new app.Ball(0, 0, 28, 1, -2, "kmdjs");
    var vp = util.bom.getViewport();
});

而且,在循环依赖的场景,因为执行顺序的问题,会导致第一种方式注入undefined,所以循环依赖的情况下只能用full namespace的方式来调用。

这种编程体验虽然已经足够好,但是可以更好。怎样才算更好?

不用依赖注入function

不用写full namespace,自动匹配依赖

如下所示:

kmdjs.define("main",["util.bom","app.Ball","util.dom.test"], function() {
    var ball = new Ball(0, 0, 28, 1, -2, "kmdjs");
    var vp = bom.getViewport();
});

这就要借助uglifyjs能力,把function的字符串替换成带有namespace就可以实现上面的效果。

uglifyjs依赖分析和代码重构
function fixDeps(fn,deps) {
    var U2 = UglifyJS;
    //uglify2不支持匿名转ast
    var code = fn.toString().replace("function","function ___kmdjs_temp");
    var ast = U2.parse(code);
    ast.figure_out_scope();
    var nodes = [];


    ast.walk(new U2.TreeWalker(function (node) {

        if (node instanceof U2.AST_New) {
            var ex = node.expression;
            var name = ex.name;
            isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(ex.scope, name) || nodes.push({name:name,node:node});
        }

        if (node instanceof U2.AST_Dot) {
            var ex = node.expression;
            var name = ex.name;
            var scope = ex.scope;
            if (scope) {
                isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(ex.scope, name) || nodes.push({name:name,node:node});
            }
        }

        if (node instanceof U2.AST_SymbolRef) {
            var name = node.name;
            isInWindow(name) || isInArray(nodes, node) || isInScopeChainVariables(node.scope, name) || nodes.push({name:name,node:node});
        }
    }));

    var cloneNodes = [].concat(nodes);
    //过滤new nodes 中的symbo nodes
    for (var i = 0, len = nodes.length; i < len; i++) {
        var nodeA = nodes[i].node;
        for (var j = 0, cLen = cloneNodes.length; j < cLen; j++) {
            var nodeB = cloneNodes[j].node;
            if (nodeB.expression === nodeA) {
                nodes.splice(i, 1);
                i--;
                len--;
            }
        }
    }

    for (var i = nodes.length; --i >= 0;) {
        var item = nodes[i],
            node=item.node,
            name=item.name;
        var fullName=getFullName(deps,name);
        var replacement;
        if (node instanceof  U2.AST_New) {
            replacement = new U2.AST_New({
                expression: new U2.AST_SymbolRef({
                    name:fullName
                }),
                args: node.args
            });
        } else if (node instanceof  U2.AST_Dot) {
            replacement = new U2.AST_Dot({
                expression: new U2.AST_SymbolRef({
                    name: fullName
                }),
                property: node.property
            });
        }else if(node instanceof U2.AST_SymbolRef){
            replacement = new U2.AST_SymbolRef({
                    name: fullName
            });
        }

        var start_pos = node.start.pos;
        var end_pos = node.end.endpos;

        code = splice_string(code, start_pos, end_pos, replacement.print_to_string({
            beautify: true
        }));
    }
    return code.replace("function ___kmdjs_temp","function");
}

function getFullName(deps,name){
    var i= 0,
        len=deps.length,
            matchCount= 0,
            result=[];

    for(;i1){
        throw "the same name conflict: "+result.join(" and ");
    } else if(matchCount===1){
        return result[0];
    }else{
        throw " can not find module ["+name+"]";
    }
}

function splice_string(str, begin, end, replacement) {
    return str.substr(0, begin) + replacement + str.substr(end);
}

function isInScopeChainVariables(scope, name) {
    var vars = scope.variables._values;
    if (Object.prototype.hasOwnProperty.call(vars, "$" + name)) {
        return true;
    }

    if (scope.parent_scope) {
        return isInScopeChainVariables(scope.parent_scope, name);
    }

    return false;
}

function isInArray(arr,name){
    var i= 0,len=arr.length;
    for(;i

通过上面的fixDeps,可以对代码就行变换。如:

 console.log(fixDeps(function (A) {
        var eee = m;
        var b = new A();
        var b = new B();
        var c = new C();
        var d = G.a;
    },["c.B","AAA.G","SFSF.C","AAAA.m"] ))

输出:

function (A) {
        var eee = AAAA.m;
        var b = new A();
        var b = new c.B();
        var c = new SFSF.C();
        var d = AAA.G.a;
}

这样,kmdjs在执行模块function的时候,只需要fixDeps加上full namespace就行:

function buildBundler(){
    var topNsStr = "";
    each(kmdjs.factories, function (item) {
        nsToCode(item[0]);
    });
    topNsStr+=  kmdjs.nsList.join("
") +"

";
    each(kmdjs.factories, function (item) {
        topNsStr+=item[0]+" = ("+ fixDeps(item[2],item[1])+")();

" ;
    });
    if(kmdjs.buildEnd) kmdjs.buildEnd(topNsStr);
    return topNsStr;
}

build出来的包,当然全都加上了namespace。再也不用区分循环依赖和非循环依赖了~~~

Github

上面的所有代码可以Github上找到:
https://github.com/kmdjs/kmdjs

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79667.html

相关文章

  • 隐形巨头华三通信:多年耕耘 打造云计算“大同世界”

    摘要:华三通信云计算产品线总裁吴健这样说到。虽然低调如斯,但这丝毫没有影响华三通信在云计算领域内的江湖地位。相比起来,华三通信发布的超融合系统产品则更加广为人知。  从引力波到AlphaGo,从虚拟现实到新能源,从电子政务到云课堂,云计算早已不再是高高在上的概念,而是已经渗透到了科技、工作、生活的每一个角落。  云计算的大行其道,不但改变了科技行业原有的技术路线,更是改变了既有的产业格局,创新、融...

    ivyzhang 评论0 收藏0
  • fir.im Weekly - 如何打造真正工程师文化

    摘要:英文原文链接中文翻译链接中文翻译来自微信公众号董老师在硅谷前豆瓣首席架构师如何保持团队的技术氛围在技术团队建立起技术导向的价值观良好的工程师文化,才能保持一个技术团队的创新与活力。 好的工程师,无法忍受低效且无趣的工作。优秀的技术团队应该自上而下的地推进技术平台化建设、DevOps、自动化构建、测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等。 先来看看...

    Raaabbit 评论0 收藏0
  • fir.im Weekly - 如何打造真正工程师文化

    摘要:英文原文链接中文翻译链接中文翻译来自微信公众号董老师在硅谷前豆瓣首席架构师如何保持团队的技术氛围在技术团队建立起技术导向的价值观良好的工程师文化,才能保持一个技术团队的创新与活力。 好的工程师,无法忍受低效且无趣的工作。优秀的技术团队应该自上而下的地推进技术平台化建设、DevOps、自动化构建、测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等。 先来看看...

    codecook 评论0 收藏0
  • kmdjs和循环依赖

    摘要:从很早的版本就开始,是支持循环依赖的。比如下面的代码会被编译成要支持循环依赖其实有个要求,就是。不是的循环依赖是无解的循环依赖。所以在初始化阶段,这样的循环依赖是被允许的,因为都是。 循环依赖 循环依赖是非常必要的,有的程序写着写着就循环依赖了,可以提取出一个对象来共同依赖解决循环依赖,但是有时会破坏程序的逻辑自封闭和高内聚。所以没解决好循环依赖的模块化库、框架、编译器都不是一个好库、...

    AlienZHOU 评论0 收藏0
  • 前沿·探索·想象力,今年云栖大会有啥不一样?

    摘要:本次社区和云产品共同发布新一代版本。月,我们杭州云栖大会见原文链接版权声明本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。 ...

    malakashi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<