• AMD and CMD are dead之KMD.js之懒


    缘由

    “懒”在软件设计中,有着重大的意义。最常见的两种“懒”,便是:

    懒得计算

    懒得加载

    “懒得计算”常见于服务器端:

    比如Multiplayer Online Role-PlayingGame,客户端主动计算,游戏服务器平滑过渡,在性能、游戏同步性找一个合适恰当的点。其目的是节约服务器端CPU、内存等的消耗,把许多消耗性能的计算分布在玩家电脑上;

    比如cache,任何cache的目的都是:懒得重新计算,因为我已经计算过了。

    比如web应用的表单校验,在数据提交给服务器前进行数据有效性校验,当然这样的目的不是为了省去服务器端的校验,客户端与服务器双校验是必须的,只是过滤一部分正常手段提交错了的格式信息,从而偷一定程度的懒;

    “懒得加载”常见于浏览器端:比如图片、视频、音频、css、js等的加载。

    拿最常见的焦点图滚动来说:焦点图什么时候初始化完毕?等所有图片加载完成还是第一张图片加载完成?这里可以好好考虑延迟加载。

    比如一三屏的网页,用户打开时候处于第一屏?第二屏和第三屏的图片是否要加载?还是根据用户所处的viewport去加载viewport内部的图片?

    OK,上面说的都跟本文无关,本文主要讲的是js按需加载。

    举个场景

    有这样一个页面:

    image

    如你所见,用户打开网站,页面有一个a标签,点击可跳转到美女网站,页面还有一个按钮,点击可产生一个运动的小球。如下图所示:

    image

    所以专门正对小球抽象出一个对象Ball.js:

    define("Ball", {
        init: function (x,y,r,vx,vy,text) {
            this.x = x;
            this.y = y;
            this.r = r;
            this.d = 2 * r;
            this.vx = vx;
            this.vy = vy;
            this.text = text;
            this.element = document.createElement("div");
            this.element.innerHTML = text;
            this.element.style.cssText = "text-align:center;position:absolute; -moz-border-radius:" + this.d + "px; border-radius: " + this.d + "px;  " + this.d + "px; height: " + this.d + "px;background-color:green;line-height:" + this.d + "px;color:white;";
            document.body.appendChild(this.element);
            var self = this;
            this.loop = setInterval(function () {
                self.tick();
            }, 15)
        },
        tick: function () {
            this.x += this.vx;
            this.y += this.vy;
            this.element.style.left = this.x + "px";
            this.element.style.top = this.y + "px";
        }
    })

    后来,网站架构师经过随机抽样统计,发现打开这个页面的10000人当中,其中有9999人点击了美女网站直接跳转去看美女了,而仅剩的1人还是个女同胞,打开该页面后立马直接关闭,生怕自己老公发现这块宝地。最后统计的结果就是:那个create a ball 的就根本没有人按过。

    既然create a ball从未有人点击,那么这个Ball.js就白白加载了,浪费了用户带宽。

    这种场景在各种网站中太多了,比如youku登录相关的弹出层的js,弹出层里表单验证的js。用户进入页面的时候可能仅仅只是想要看视频。所以登录相关的js可以延迟到用户点击登录之后再进行加载和执行。当然这个是js非常小,影响甚微,但是如果某一项目板块特别大粒度,按需加载执行就特别重要。

    解决方案

    KMDjs作为JS工程化终极解决方案,以Kill AMD和CMD为己任,肯定会提供相关的解决方案。

    先说一下,KMDjs的懒执行。这点KMDjs开销真的是太小了,因为大部分逻辑都在init才真正执行,所以KMDjs模块ready的开销仅仅是创建类。

    KMDjs又是怎么解决懒加载的呢?不卖关子,直接上码:

    var crtBtn = document.getElementById("crtBtn");
    var balls = [];
    crtBtn.onclick = function () {
        kmdjs.get("HelloKMD.Ball", function (Ball) {
            var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
            balls.push(ball);
        });        
    }

    当然,也支持 promise style:

    kmdjs.get("HelloKMD.Ball").then(function (Ball) {
        var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
        balls.push(ball);
    });

    初衷受挫

    其实,上面不是我最初想要的lazy方式。我最初想要的是这样的结果:

    kmdjs.config({
        name:"HelloKMD",
        baseUrl: "js",
        classes: [
            { name: "HelloKMD.Ball", lazy:true },
            { name: "Util.Bom",url:"Util" }
        ]
    
    });
    define("Main",["Util"], {
        init: function () {
    
            var crtBtn = document.getElementById("crtBtn");
            var balls = [];
            crtBtn.onclick = function () {
                var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
                balls.push(ball);
            }
            var vp = Bom.getViewport();
            setInterval(function () {
                for (var i = 0, len = balls.length; i < len; i++) {
                    var ball = balls[i];
                    (ball.x + ball.r * 2 > vp[2] || ball.x < 0) && (ball.vx *= -1);
                    (ball.y + ball.r * 2 > vp[3] || ball.y < 0) && (ball.vy *= -1);
                }          
            }, 100)
        }
    })

    可以看到代码没有任何更改,只不过在config里稍微配置了一番,但这几乎要把wind.js集成进来,把

    var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");

    变成

    var ball=$await(new Ball(……..));

    而且要去分析ast,还要去分析current scope,还要遍历scope tree,还要去考虑build的问题,还要去…

    最终我放弃!选择了这种kmdjs.get的还不错的方式。如果你有更好的想法、建议或意见,请第一时间告诉我,我会将其糅合进0.0.3版本当中。

    地址

    https://github.com/kmdjs/kmdjs

    目前还是0.02版本,kmdjs.get将在0.0.3出现…

  • 相关阅读:
    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
    聊聊高并发系统之限流特技
    Java程序员 必须掌握的 20+ 种 Spring 常用注解
    这20个核心技术,作为Java开发程序员,你一定要掌握
    40K刚面完Java岗,这些技术必须掌握
    Java 5,6,7,8,9,10,11新特性超详细总结
    小米程序员的忧虑:感觉互联网这两年要凉,想回家种地
    Java技术文档—Java中的运算符有哪些?
    Java笔记之数组,异常处理,集合知识要点
    Java学习笔记——IO流基础知识点整理
  • 原文地址:https://www.cnblogs.com/iamzhanglei/p/3816079.html
Copyright © 2020-2023  润新知