html中require.config 緩存問題

在html中,require的官方基本用法如下:

<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>

 但在實踐過程中,我們可能會有很多需要配置的,比如jquery…

然後我們大約會把這些配置寫到配置文件,如下:

// require.config.js

require.config({ paths: { jquery :
"/js/library/jquery.min", }, shim : { } });

 然後,再在  main.js  中引用

//mian.js
require(["/js/require.config.js"],function(){
    "use strict";
    require(["jquery"], function ($) {
        //功能代碼
    });
})

因為網頁緩存問題,這種方式存在當 require.config.js 有修改時,客戶端的 require.config.js 並不會更新的問題。同時如果有多個html都用了require,那每個模塊的 main.js 都需要在頭部加上述代碼。

既然在require中引用 config,會有緩存問題,那我就把  require.config.js  放到 html ,並且增加版本控制。但需要注意的是, rquire.config.js  必須放到  require.js  後面,因為他用到了require類。

如下

<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
        <script src="scripts/require.config.js?v=xxx"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>

這種形式會存在一個新的問題:當 require.config.js  修改後,由於   require.js  已經在瀏覽器緩存,所以很快(快到  require.config.js 還未加載完成)就會加載  main.js ,此時 man.js 沒有享受到  require.config.js 中的配置。

這裡我想到了  require.js  的模式(先加載  require.js , 再加載  main.js )與現在的需求(先加載 require.config.js ,再加載 main.js )大概相同。所以看了  require.js  中的實現,把相關部分的代碼複製到  require.config.js 。

最終,我使用的代碼樣例如下:

需要注意的是:html 中,需要移動 data-main 的位置:

<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        
             scripts/main.js after require.js loads. -->
        <script src="scripts/require.js"></script>
        <!-- data-main 移動到這裡 -->
        <script src="scripts/require.config.js?v=xxx" data-main="scripts/main" ></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>    
// require.config.js
;(function () {

    let rev = 'xxxx';


    let cfg = {
        // 不設置超時 = 0
        waitSeconds: 60,
        
        paths: {
            'jquery': '../../../../Common/Common/jquery-3.3.1/dist/jquery.min',
            
        },
        shim: {
            'jquery': {exports: 'jQuery'},
            
        },
        urlArgs: function (id, url) {
            if (url.indexOf('http') === 0) {
                return '';
            }
            let args = `rev=${rev}`;
            // /Common/Common 下的文件不用版本控制, 都是 3 方庫
            if (url.indexOf('/Common/Common/') >= 0) {
                args = 'v=2'
            }
            return (url.indexOf('?') === -1 ? '?' : '&') + args;
        }
    };

    let dataMain = '';
    let scripts = document.getElementsByTagName('script');
    for (let i = scripts.length - 1; i > -1; i -= 1) {
        let script = scripts[i];
        let src = script.getAttribute('src');
        if (src.indexOf('require.common.config.js') > 0) {
            dataMain = script.getAttribute('data-main');
            if (dataMain) {
                //Preserve dataMain in case it is a path (i.e. contains '?')
                let mainScript = dataMain;

                //Set final baseUrl if there is not already an explicit one,
                //but only do so if the data-main value is not a loader plugin
                //module ID.
                if (!cfg.baseUrl && mainScript.indexOf('!') === -1) {
                    //Pull off the directory of data-main for use as the
                    //baseUrl.
                    src = mainScript.split('/');
                    mainScript = src.pop();
                    let subPath = src.length ? src.join('/') + '/' : './';

                    cfg.baseUrl = subPath;
                }
            }
            break;
        }
    }

    require.config(cfg);

    if (dataMain) {
        require([dataMain]);
    }

}());