seajs模块化改造实践

前言

一月份的时候,临近放假,拿到一个需求,新增一个产品,我一个前端对一个java后端,两个星期的开发时间。 因为大部分功能在别的产品都已经有了,基本都是简单处理一下拿过来,再添加一下额外需要的功能,比如选择出行国家等。前一天拿到文档看了下,搞清楚之后,第二天开工,基本一天就把功能做完了。这一天的大部分时间还是花在-找代码上。无他,实在是遗留的代码 不是很清晰。

因为系统比较旧,前后端也没有分离,jsp的,代码也很混乱,逻辑里面还有很多奇怪的注释,在这些上面做了很多无用功。 基本做好功能,联调测试,通过之后基本就OK了。

但是两个周的时间才用了两三天。还有十来天呢,怎么办呢,看着这些混乱的代码,本着造福别人,也为以后的方便,就想着,用模块重新组织一下吧。因为去年有过这方面经验,轻车熟路。所以,就有了后来的故事和今天的这篇文字。

改造前

改造前的代码大概是这个样子的:

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        


        
            
            
            
            
            
            特别约定
             
            
            
            
            
标准保费 元/人
优惠价 元/人

不多贴代码了,大概就是这个样子的。这种情况的原因大概是:

1.起初的页面是后端人员写的,没有很好的组织各种资源。写到一定数量之后,各种逻辑已经耦合在一起,别的人接手之后,又不敢乱改,就按以前的做法复制粘贴,做好自己的那一块。久而久之,页面就越来越复杂,冗余也越来越多,形成了一个恶性循环。

2.网络环境不允许。使用公司标配的联想笔记本,标装之后,收到公司安全策略的限制,很多技术网站无法访问,查资料有时候只能看百度快照,有些同事只好用手机或者自带电脑来解决这个问题。至于 github,google,基本是不可能的。

3.没有代码规范。基本每个人都是按照自己的风格来,最后归并之后的代码就显得很混乱。

由于不能使用脚手架自动化工具,这种情景要做模块化,requireJs/seaJs 是比较好的选择。去年用过requireJs,这次就用一下seaJs.

由于项目中的样式文件实在太多太杂,时间上不允许我重新组织一遍,所以就只对逻辑代码做了模块化处理。

组织模块

要组织模块,首先要弄清楚相应的规则。最好的方式当然是看 seajs文档 了.

这里也简单介绍下几个常用的功能。

    
    // 页面中包括的js
    
    

    
    

    

再看一下配置信息:

    seajs.config({
    base:"./js/",
    paths: { //当目录比较深,或需要跨目录调用模块时,可以使用 paths 来简化书写。 
           "seajs": "seajs/2.3.0/sea.js"
    },
    alias:{ // 设置别名,方便调用 , 当模块标识很长时,可以使用 alias 来简化。
        "jquery" : "lib/jquery/1.10.0/jquery.min.js",
        'Hello':'mod/mod4.js',
    },
    map: [
        [".js",".js?1.0"]
    ],
    debug:true //值为 true 时,加载器不会删除动态插入的 script 标签。插件也可以根据 debug 配置,来决策 log 等信息的输出。
});

然后是页面入口:

//main.js

/*
    define define(factory)

    define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串。

    factory 为对象、字符串时,表示模块的接口就是该对象、字符串。比如可以如下定义一个 JSON 数据模块:

    define({ "foo": "bar" });
    也可以通过字符串定义模板模块:

    define('I am a template. My name is {{name}}.');
    factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:require、exports 和 module:

    define(function(require, exports, module) {

      // 模块代码

    });
*/
define(function (require, exports, module) {

    var $ = require('jquery');
    
    console.log($); 
            
    require('mod1');
    
    var Hello = require('Hello');
    
        Hello.init();
        
        
    // other code...
        
});

看一下模块内的代码:

//mod1.js
    define(function (require, exports, module) {
        console.log('mod1加载完毕');
});
//mod4.js
define('Hello',function(require,exports, module) {

    var Hello = {
            sayHello:function(){
                console.log('hello');
            }  
    }

    module.exports = Hello;
});

打开页面控制台,就会看到输出的信息:

seajs模块化改造实践_第1张图片

说明我们的模块已经被成功的被加载了。

当然 实际的工作中还要用到各种插件,这就需要知道如何改造现有文件为 CMD 模块

这些在文档中都能找到。

以上简单介绍了使用seajs 组织模块的方法。

当然,模块写完之后呢,我们还需要相应的构建工具。

玉伯说:

如果使用 Sea.js,强烈推荐采用配套的构建工具来压缩、合并代码。如果不这么做,可能会带来不少额外的工作甚至隐患。

如果不合并代码,也能运行,你会看到你的插件代码都会以async的方式插入到页面的头部。而且需要你手动处理依赖关系,也产生了额外的请求,不是很友好。如下图:

seajs模块化改造实践_第2张图片

所以,为了避免意外的发生,也为了减少请求数,应该合并模块。

我们来看一个实际的例子-支付宝的登陆页面。

在网页支付宝收银台中的运用

seajs模块化改造实践_第3张图片

![clipboard.png]
seajs模块化改造实践_第4张图片

seajs模块化改造实践_第5张图片

很直观的就能看到插模块的合并,这个合并的工作就是构建工具的功劳了。

我们也来实现一下。

先看效果吧,执行模块合并之后,入口文件可以是这样的:

seajs模块化改造实践_第6张图片

这样就实现了模块的打包合并。

我这里使用了gulp来实现这一步, 代码如下:

//seajs合并模式
gulp.task("seajs", function () {
    return merge(
        gulp.src(src + '/js/!(lib)/**/*.js', {base: src + '/js'})
            .pipe(transport())
            .pipe(concat({
                base: src + '/js'
            }))
            .pipe(replace({
                patterns: replace_patterns
            }))
            .pipe(gulp.dest(dist + '/js')),

        gulp.src([src + '/js/lib/**/*.js', src + '/js/common.js'], {
                base: src + '/js'
            })
            .pipe(replace({
                patterns: replace_patterns
            }))
            .pipe(gulp.dest(dist + '/js'))
    );
});

使用gulp提取模块有其他更详细的教程,这里提供一个我认为比较好的:

介绍一种基于gulp对seajs的模块做合并压缩的方式

那个支付宝的登陆页 这里给出完整代码,给大家观摩:







支付宝快捷收银台




















    
加载中...

登录支付宝

返回
忘记密码
mobileclientgw-30-5

改造后

改造到最后呢,页面逻辑清爽多了,再有新的模块,写好之后别人直接调用就可以了,write once, run everywhere .

define(function(require) {

    var $ = require("jquery"),
        $body = $(document.body),
        setDate = require("components/setDate"),
        selectCity = require("components/selectCity"),
        commonTools = require("tools/commonTools"),
        FastClick = require("fastClick"),
        myLayer = require("myLayer");


    //内部统计
    var webTrends = require("webTrends");
    webTrends.init();

    // 百度统计
    var baiduTrends = require("baiduTrends");
    baiduTrends.init();

    // 初始化时间选择
    setDate.dateTime.init();
    
    //  选择目的地
    selectCity.init();

    var actionList = {

      'applyInsurance' :function(){
          //xxx
      }
  });    

完整的代码就不展示了,都是一些逻辑,没什么好看的。

最后

花了大概一个周的时间初步重构了一下项目代码,改得很粗糙,只是做了一些大概的拆分,毕竟遗留的代码太多,需要和小伙伴一起做这个事。

由于公司标装的电脑用不了npm那些,最后的一步是我在mac上弄好,然后拷贝到公司电脑上,中间还出了很多问题,不过好在能跑了,至于最后能不能用起来..只能说,努力吧。

seajs 可以说是上个年代的产物了,不过在一些老旧项目中,依然可以发挥光和热。

写到这里差不多也要结束了,我呢,也算完成了给自己定的一个小目标,不算多大的贡献,只当给自己一个交代。

以上大概就是全部内容,希望给大家带来一些启发和帮助,谢谢。

你可能感兴趣的:(模块化开发,seajs,javascript)