html中require.config 緩存問題
- 2020 年 5 月 16 日
- 筆記
- HTML, js, require.config, requirejs
在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]); } }());