web性能优化之模块化

作者: Timeless 更新时间: 阅读量: 356

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是一套基于浏览器端模块化开发的规范,在进行页面开发时需要用到该规范的库函数。袋盐:RequireJS

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中文网,现在我只写过sea.js相关的东西,require.js后面再写

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

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

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

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);
            });
        });
    }
});

本站就是使用Sea.js做模块化加载js的喵~,你瞅瞅只有底部sea.js要控制js的加载,不过是在学习阶段写的,不是很规范的说

webpack模块化

webpack的模块不仅指js,包括css、图片等资源都可以以模块看待,但是但是有时候只需要对js进行模块化,反正我只看上webpack的loader和插件,用后端语言做MVC多了不太习惯webpack来加载图片啊、字体啊

不过安啦,下面的代码应该还是可行的,这个后面也会写些学(ru)习(keng)日志哒

//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我用的不是很多,希望在以后实战多了之后再来完善

类似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

后面2个有空再完善

成长路上的小白一枚,写得不好请见谅