web性能优化之模块化

web性能优化之模块化

2018-06-25 374

web模块化其实就是将一个完整的单一的功能整合起来形成单独的一个功能组件,当需要用的的时候只需要加载这个组件,然后便可以通过该组件唯一的名称去使用其中的内容。模块之间通过API进行重组。

优点:高内聚低耦合,有利于团队作战,方便维护 ,重用;

           不阻塞页面渲染 ,异步按需加载

缺点:模块化开发会复杂化开发逻辑,视方法而定模块是否需要实行一些规范,有些模块之间还有依赖关系(有时候一些库或者框架要实现包管理用新的方法才有文档可循)

主流模块化:common.jsAMDCMDwebpackES6

CommonJS

定义模块:即一个单独的文件就是一个模块,切该文件中的作用域独立,当中的变量是无法被其他文件引用的,如果要使用需要将其定义为global;

输出模块:模块只有一个出口,即使用module.exports对象,将需要输出的内容放入到该对象中;

加载模块:通过require加载,例如:var module = require('./bundle.js');module的值即对应文件内部的module.exports对象, 然后就可以通过module名称去引用模块中的变量和函数了;

// 定义模块 module.js
function showmmsg() {
    var msg = "Hello commonJS !";
    console.log(msg);
}
// 输出模块
module.exports = {
    myfunction: showmsg
}
// 加载模块
var module = require('./module.js');
// 使用模块功能
module.myfunction(); // "Hello commonJS !"

AMD(Asynchronous Module Definition),异步模块定义

AMD是一套基于浏览器端模块化开发的规范。异步加载模块,可并行加载,适用于浏览器

代表:require.js(依赖前置)

优点:1、防止js加载阻塞页面渲染,可以按需、并行载入js

           2、使用了块作用域来申明function防止污染全局变量

// 模块定义 module.js
define(
    ['dependModule', '...', ...], // 这个数组表示该模块所依赖的模块名称 
    function showmsg() {
        var msg = "Hello AMD !";
        console.log(msg);
    }
    return {
        myfunction: showmsg
    };
});
// 加载模块
require(['module'], function (__this) {
// 加载之后的module模块将会以参数形式:myModule传入到回调函数中,供使用
// 这里是模块加载完成之后的回调函数
    __this.myfunction(); // "Hello AMD !"
});

关于多模块、依赖关系,以及require.js的配置等等,请移步 Require.js中文网

CMD(Common Module Definition),通用模块定义

异步加载模块,依赖就近,延迟执行,适用于Node.js、浏览器

就近依赖,需要时再进行加载,所以执行顺序和书写顺序一致require.async;这点与AMD不同,AMD是在使用模块之前将依赖模块全部加载完成(在定义模块的时候就要声明其依赖的模块),但由于网络等其他因素可能导致依赖模块下载先后顺序不一致这就导致了,执行顺序可能跟书写顺序不一致的情况。

代表:Sea.js 推崇一个模块一个文件,遵循统一的写法 

优点:1、提升代码的可维护性

        2、防止js加载阻塞页面渲染 (其实和require差不多)

// 模块定义 module.js
define(function(require, exports, module) {
    var $ = require('jquery'); //依赖jq,但是其实下面的代码没有使用jq
    exports.sayHello = function() {
        var msg = "Hello CMD !";
        console.log(msg);
    };
});
seajs.config({
  alias: {
    'jquery': 'http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js'
  }
});
// 加载模块
seajs.use(['./module', 'jquery'], function(module, $) {
    module.sayHello();
});

模块间的调用,通过exports创建对外api,详情 Sea.js手册与文档

//common.js
define(function(require, exports, module) {
    require('layui');
    exports.AddFavorite=function (title, url) {
        try {
            window.external.addFavorite(url, title);
        } catch(e) {
            try {
                window.sidebar.addPanel(title, url, "");
            } catch(e) {
                layui.use('layer', function(){
                    var layer = layui.layer;
                    layer.msg('抱歉,您所使用的浏览器无法完成此操作。\n\n加入收藏失败,请使用Ctrl+D进行添加',{icon: 5});
                });
            }
        }
    }
});
//main.js
define(function(require, exports, module) {
    if(page_module===1){
        //判断按需加载
        require.async('/js/common.js',function(__this){
            $(".header--top .AddFavorite").on("click",function(){
                __this.AddFavorite(document.title,location.href);
            });
        });
    }
});

webpack模块化

webpack的模块不仅指js,包括css、图片等资源都可以以模块看待

//bundle.js
exports.showmsg = function () {
    const msg = 'Hello webpack !'
    return console.log(msg);
}
//使用 index.js
var bar = require('./bar');
function foo() {
    return showmsg ();
}
//webpack.config.js
var path = require("path");
module.exports = {
    entry: path.join(__dirname, './src/index.js'),
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    }
};

ES6模块化

ES6内置了模块化的实现

定义暴露模块 : export

引入使用模块 : import

类似commonJS,语法更简洁;类似AMD,直接支持异步加载和配置模块加载;

//模块定义 module.js
export const globaldata = 'Hello ES6 !';
export function sum( x, y ) {
    return x + y;
}
//使用模块
import { globaldata, sum } from 'module';

console.log(globaldata); // Hello ES6 !
console.log(sum(6, 6)); // 12

后续完善~

评论(0)

还没有评论,快来抢第一吧