前端工程化实践一 (seajs to requirejs)

近一个月里和同事一块儿将刚接手系统从sea.js切换到require.js。一方面感受requirej比seajs更容易作工程化,一方面sea.js目前不更新了,而require社区仍然比较活跃。没有直接上vue或者react之类新潮的框架,是考虑到目前系统功能已经相对稳定了,业务复杂,组件数量不少,伤筋动骨的换框架一方面时间有限,一方面项目没有作单元测试,风险太大,后面新项目起来的话应该是会直接上react了。sea切换到require的改动相对来讲比较固定,能够彻底不动原有业务代码,工做量和风险可控。vue

不过我的其实对requirejs自己不太了解,期间仍是掉进了几个坑里的。先总结下在切换到requirejs中遇到的两个问题吧。react

1.requirejs不像seajs要求js文件被define、require包裹,能够直接require一个不符合规范的js数组

module1:
    (function(){
        window.myModule1 = {
            info:'module1'
        }
    })();
    
module2:
    (function(){
        if(window.myModule1){
            console.log(window.myModule1.info);
        }
    })();
    
main:
    require(['./module1', './module2'], function(){
        ...
    })

以上代码彻底能够正常运行,不会报错。但会发现一个问题,屡次执行的结果会不一致,这是由于module1和module2不是按照require数组参数里的顺序加载的,这种状况下没有固定的加载顺序。
有两种处理方式:
若是两个js都是业务代码能够自行维护,就把两个js都改为AMD规范缓存

module1:
    define('module1', function(){
        window.myModule1 = {
            info:'module1'
        }
    });
    
module2:
    require(['module1'], function(){
        console.log(window.myModule1.info);
    })
    
main:
    require(['./module2'], function(){
        ...
    })

若是js是外部插件,尽可能用不改源码的方式让两个js的加载变得有序。须要在require的config.js配置文件中加入一段代码,让requirejs知道两个js之间的依赖关系,保证module2在module1加载后再加载框架

requirejs.config({
    paths: {
        "module1": "./module1",
        "module2": "./module2"
    },
    shim:{
        "module2": ["module1"]
    }
})

2.require返回的对象全局共享一个。异步

module1:
    define('module1', [], function(){
        return {
            val : 0,
            init : function(){
                return this;
            },
            add : function(num){
                this.val += num;
            }
        };
    });

main:
    require(['module1'], function(m){
        m.init().add(1);
        console.log(m.val);  //1
    });
    require(['module1'], function(m){
        m.init().add(1);
        console.log(m.val);    //2
    });

以上例子说明,module1第一次被require之后,返回的对象m会被缓存起来,第二次被require的时候,返回的是以前缓存起来的m。屡次require同一个模块时,返回的对象其实是同一个。这与seajs是不一样的,seajs每次异步加载都会返回一个,之前基于seajs写的代码里切换成require之后就会留下潜在的坑。
解决方法简单粗暴,全部返回对象的地方全换成返回function,执行function返回原对象。requirejs

module1:
    define('module1', [], function(){
        return function(){
            return {
                val : 0,
                init : function(){
                    return this;
                },
                add : function(num){
                    this.val += num;
                }
            }
        };
    });
    
main:
    require(['module1'], function(m){
        m().init().add(1);
        console.log(m.val);  //1
    });
    require(['module1'], function(m){
        m().init().add(1);
        console.log(m.val);    //1
    });
相关文章
相关标签/搜索