項目優(yōu)化再會requirejs

requirejs好久不見。

技術(shù)不存在過時一說,合適就好。

RequireJS就是一個工具庫,它的模塊管理遵守[AMD規(guī)范],通過define方法,將代碼定義為模塊;通過require方法,實現(xiàn)代碼的模塊加載。

最近因為一個老的項目要做優(yōu)化,該項目用requirejs做的模塊加載,說起來
這個項目架子還是甚為奇。

MVC------------M和C用的是backbone,V選擇了React,而且還引入了 JSX。
代碼中使用了很多的第三方庫,另外所有的UI公共組件都是單一的jsx文件,jsx文件是一個define定義的AMD模塊(但是內(nèi)部使用了React.createElement,沒看到j(luò)sx的語法)。

經(jīng)過分析,整體上目前上的優(yōu)化手段有

1, 所有的同步ajax優(yōu)化為異步---代碼中竟然很多使用了(無特殊情況)同步的ajax請求

2, 首頁資源加載方式優(yōu)化----(首頁document.write阻塞的方式,加載一些資源文件)

3, 全局加載資源優(yōu)化,對冗余資源去冗

4, 靜態(tài)資源分域伺服提供加載,優(yōu)化加載性能.

5, 前后端分離

6, 靜態(tài)資源開啟gizp壓縮優(yōu)化,調(diào)解最小文件大小為適當(dāng)值。

以上的手段優(yōu)化后,在其中一個復(fù)雜的多表單共存的頁面,該頁面在第一次打開時拉取.jsx得請求數(shù)竟然到達100多個,嚴(yán)重影響該頁面性能。

經(jīng)過分析,還記得前文我們說的每個UI組件都是一個jsx文件,在當(dāng)前這個復(fù)雜的頁面,基本上80%以上的組件都會用上,所以該頁面打開時,會通過XHR去獲取所有的jsx文件,理解AMD模塊的化,應(yīng)該理解,必須 在jsx文件獲取后,才會執(zhí)行回調(diào)函數(shù)的邏輯。因此改頁面所需要的jsx必須要適當(dāng)?shù)暮喜ⅰ?/p>

define(["react","jsx!js/component",,"jsx!js/multi"],function(React,Component,Multi){
  //code
   require(["jsx!js/component1",,"jsx!js/multi2"],function(Component1,Component2){
        //code
           ....
   })
   ....
})

那怎么合并呢?

肯定不是簡單的把文件合起來就好,必須做好他的依賴管理,否則當(dāng)組件間存在依賴時,就會出問題,找不到某個模塊報undefined錯誤。

因此回過頭,我們再一起看看requirejs

模塊定義

無依賴的模塊

define(function () {
    return {
        method1: function() {},
        method2: function() {},
    };
});

有依賴的模塊

define(['module1', 'module2'], function(m1, m2) {
   ...
});

模塊調(diào)用

1.require(['foo', 'bar'], function ( foo, bar ) {
        foo.doSomething();
});

2. define內(nèi)注入require
define(function ( require ) {
    var isReady = false, foobar;
 
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });
 
    return {
        isReady: isReady,
        foobar: foobar
    };
});

3. 異步
define(['lib/Deferred'], function( Deferred ){
    var defer = new Deferred(); 
    require(['lib/templates/?index.html','lib/data/?stats'],
        function( template, data ){
            defer.resolve({ template: template, data:data });
        }
    );
    return defer.promise();
});

錯誤處理

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
    }
});

//Later
require(['jquery'], function ($) {
}, function (err) {
   
    var failedId = err.requireModules && err.requireModules[0];
    if (failedId === 'jquery') {
     
        requirejs.undef(failedId);

    
        requirejs.config({
            paths: {
                jquery: 'local/jquery'
            }
        });

        
        require(['jquery'], function () {});
    } else {
       
    }
});

配置

require.config({
    paths: {
        "backbone": "vendor/backbone",
        "underscore": "vendor/underscore"
    },
    shim: {
        "backbone": {
            deps: [ "underscore" ],
            exports: "Backbone"
        },
        "underscore": {
            exports: "_"
        }
    }
});

看到這里,該文件合并了吧,對~~~~
r.js出場了

npm install -g requirejs
node r.js -o <build.js>

build.js文件內(nèi)容

({
    appDir: './',
    baseUrl: './js',
    dir: './dist',
    modules: [
        {
            name: 'main'
        }
    ],
    fileExclusionRegExp: /^(r|build)\.js$/,
    optimizeCss: 'standard',
    removeCombined: true,
    paths: {
        jquery: 'lib/jquery',
        underscore: 'lib/underscore',
        backbone: 'lib/backbone/backbone',
        backboneLocalstorage: 'lib/backbone/backbone.localStorage',
        text: 'lib/require/text'
    },
    shim: {
        underscore: {
            exports: '_'
        },
        backbone: {
            deps: [
                'underscore',
                'jquery'
            ],
            exports: 'Backbone'
        },
        backboneLocalstorage: {
            deps: ['backbone'],
            exports: 'Store'
        }
    }
})

appDir:項目目錄,相對于參數(shù)文件的位置。

baseUrl:js文件的位置。

dir:輸出目錄。

modules:一個包含對象的數(shù)組,每個對象就是一個要被優(yōu)化的模塊。

fileExclusionRegExp:凡是匹配這個正則表達式的文件名,都不會被拷貝到輸出目錄。

optimizeCss: 自動壓縮CSS文件,可取的值包括“none”, “standard”, 
“standard.keepLines”, “standard.keepComments”,
 “standard.keepComments.keepLines”。

removeCombined:如果為true,合并后的原文件將不保留在輸出目錄中。

paths:各個模塊的相對路徑,可以省略js后綴名。

shim:配置依賴性關(guān)系。如果不是AMD模式定義的,就用shim指定模塊的依賴

generateSourceMaps:是否要生成source map文件。

一個完整的文件例子

最終本項目的的build.js如下

({
    appDir:'./',
    baseUrl: 'static',
    dir: "build",

    mainConfigFile:'./static/config.js',

    findNestedDependencies: true,
    removeCombined:true,
    generateSourceMaps:true,
    modules: [
        {
            name: "main"
        },
        {
            name: "admin"
        }
        
    ]
})

node r.js -o build.js

補充
因為沒有找到方法,用r.js去處理jsx文件,所以后來就把jsx文件全部改為js(因為里面并沒有使用 jsx語法,其實質(zhì)就是js),最終使得可以通過r.js處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近在學(xué)習(xí) Webpack,網(wǎng)上大多數(shù)入門教程都是基于 Webpack 1.x 版本的,我學(xué)習(xí) Webpack 的...
    My_Oh_My閱讀 8,320評論 40 247
  • GitChat技術(shù)雜談 前言 本文較長,為了節(jié)省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack,它要...
    蕭玄辭閱讀 12,874評論 7 110
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,836評論 25 709
  • 性能優(yōu)化方向分類 請求數(shù)量: 合并腳本和樣式表, CSS Sprites, 拆分初始化負(fù)載, 劃分主域(使用“查找...
    Www劉閱讀 1,884評論 3 8
  • 如果 有陽光 陰穢就少 如果 有溫暖 寒冷就少 如果 有正義 邪惡會少 如果 如果 那么 那么 一定 一定 反之 ...
    旖旎i閱讀 101評論 2 8

友情鏈接更多精彩內(nèi)容