本文主要講述require.js在IDEA中路徑智慧感知的辦法和探索中遇到的問題。
測試使用的目錄結構:一種典型的thinkphp 6的目錄結構,如下圖。
現在我通過在 vue-a.js 中運用不同的方式引用 ../td/data.js 檔案。其中,data.js 的內容如下:
define([], function () { let idx = 0; console.log('data.js') return 'data' + (++idx); });
方法1:使用相對路徑
優點:
- 不用配置 require.config
缺點:
- 呼叫不同的模組的js時,路徑文字長
- 在不同模組間呼叫時極易發生相對位置錯誤
方法2:使用require.config配置paths
require.config({ paths: { 'data': '../../../../public/static/admin/td/data', }, })
再在vue-a.js中使用paths中定義的短名進行引用。
define(['data'], function (data1, data2) { let vueTemplate = { data: function () { let data = { str: data1 + data2 }; return data; }, template: `<div>{{str}}</div>` }; return vueTemplate; });
優點:
- 名字短
缺點:
- 需要配置require.config
- 在輸入時無法智慧感知,如上圖。
- 無法很友好的識別匯出的物件,參見:https://www.cnblogs.com/zhongchengyi/p/12982228.html
方法3:使用絕對路徑
使用絕對路徑時需要注意,必須使用require.config配置根目錄地址的別名(程式碼如下), 否則在執行時會找不到檔案(如下圖中的路徑,最終require可能會去找檔案:src/public/static/admin/src/public/static/admin/td/data.js)。
require.config({ paths: { 'src': '../../../..', }, })
優點:
- 不用糾結當前的路徑在哪裡。
- 配置相對少(只配置了根目錄)
- 輸入時完美智慧感知
缺點:
- 需要配置require.config
- 路徑文字長
特別注意:同一個檔案不能混用引用方式
混用絕對路徑和短名
此種混用絕對不能用,會導致嚴重後果。程式碼如下:
define(['src/public/static/admin/td/data', 'data'], function (data1, data2) { let vueTemplate = { data: function () { let data = { str: data1 + data2 }; return data; }, template: `<div>{{str}}</div>` }; return vueTemplate; });
後果:
- 介面無法正常顯示
- require.js的程式碼報異常,無法進入 require後的程式碼。
- 無法載入短名代表的檔案,一直卡住,直到超時(超時時間是 require.config中配置的waitSeconds)
混用相對路徑和絕對路徑、混用相對路徑和短名
程式碼如下:
define(['../td/data', 'data'], function (data1, data2) { let vueTemplate = { data: function () { let data = { str: data1 + data2 }; return data; }, template: `<div>{{str}}</div>` }; return vueTemplate; });
define(['src/public/static/admin/td/data', '../td/data'], function (data1, data2) { let vueTemplate = { data: function () { let data = { str: data1 + data2 }; return data; }, template: `<div>{{str}}</div>` }; return vueTemplate; });
這兩種混用方式都不會導致網頁卡住,但是,會導致被引用的檔案被呼叫兩次。如圖,控制檯輸出了兩次 'data.js'。
呼叫兩次有時會導致意想不到的問題。比如有些 js 會有事件註冊的邏輯,被呼叫兩次後,會導致事件被註冊兩次。後期會非常難定位。
我的最佳實踐
- 模組內部的相互引用,可以直接用相對路徑
- 模組間的引用,使用絕對路徑
- 外部模組(三方庫)使用短名
- 模組間儘量保持層級一致
PS:檢查require的檔案是否被呼叫兩次
在 require.config 中配置 onNodeCreated 回撥。
require.config({ paths: {}, shim: {}, onNodeCreated: function (node, config, moduleName, url) { if (!this.nodes) { this.nodes = {}; } if (!this.nodes[node.src]) { this.nodes[node.src] = {node, moduleName, url}; } else { console.warn('重複的模組,如下:'); console.log(this.nodes[node.src]); console.log({node, moduleName, url}); } }, });
效果,在控制檯中輸出重複的模組的資訊。