seajs github 模塊標識已經說的相對清楚了。但並沒有面面俱到,特別是當你需要手寫【模塊ID】和【模塊依賴】的時候,或者自己寫自動化工具來做transport 的時候(ps:spm貌似適應性不是很強也不易用,畢竟每個項目的目錄結構可能相差很大,且不易改變。當然如果他的定位是包管理工具就別指望它來做你的項目的自動化構建工具了),ID的解析規則就需要了解透徹了。
注意事項:
1. 頂級標識始終相對base 基礎路徑解析。
2. 絕對路徑和根路徑始終相對當前頁面解析。
3. require 和require.async 中的相對路徑相對當前模塊路徑來解析。
4. seajs.use 中的相對路徑始終相對當前頁面來解析。
seajs中,模塊的ID大致可分為三種:【相對標識】、【頂級標識】、【普通路徑】,
普通路徑包括“絕對路徑”、“根路徑”,等。
這裡重點說明【相對標識】 和【頂級標識】。
相對標識是指"./","../" 開頭的,如:"./OtherModule", "../lib/Base"。
頂級標識是指以文件或目錄(可以包含:字母、-、_)開頭的,如:"app/widget/Select"
需要寫模塊ID的地方有三處:
複製代碼代碼如下:define("id (1)",["../id2 (2)"], function(require, exports, module){
var moduleA = require('./moduleA (3)');
})
注意:無論是define第一個參數【模塊ID】還是第二個參數【依賴模塊的ID】還是【require模塊ID】,最終的比對標準是【解析後的文件URI】。
因此,這三處需要寫ID 的地方可以以任意一種方式來寫,只要最終解析為同一個URI,即被認為是同一個模塊。
在解析ID的過程中,會預先經過seajs.config 中定義的alias 和paths 的處理。
base 路徑解析規則
(第1 層,本身的路徑不依賴於任何設置)
1. 不可使用【頂級標識】,因為頂級標識就是相對於base 基礎路徑來解析的,因此base 本身只能使用【相對標識】或【根路徑】等。
2. base 默認路徑為seajs 的目錄,其他情況參見seajs官網,如果不是seajs推薦的源碼目錄結構,盡量手動設置base 路徑。
3. 【相對標識】:相對於當前頁面解析。
paths 中路徑解析規則
(第1 層,本身的路徑不依賴於任何設置)
1. 【相對標識】:在哪裡被引用,相對的解析位置視被引用的地方而定,遵循當地的規則。
2. paths中的字段會被以變量的方式在被使用的地方替換,然後再解析。
比如:
複製代碼代碼如下://代碼塊(1)
//path定義:
seajs.config({
base:"./app/src",
path:{
"a":"../lib", //(1) 相對路徑
"lib":"path/to/lib", //(2) 頂級標識
"l2":"/lib" //(3) 根路徑
}
});
//模塊mod/m/m.js:
...
require("a/jquery");
//=> 轉換為:"../../lib/jquery"
//=> 加載:mod/lib/jquery (特別注意1)
...
//模塊mod/f.js:
...
require("a/jquery");
//=> 轉換為:"../../lib/jquery"
//=> 加載:lib/jquery (特別注意2)
...
alias 中路徑解析規則
(第2 層,本身的路徑可以依賴於paths的設置)
1. alias 的規則類似於paths,並且alias 路徑也可以使用paths 中的“變量”
2. 提醒:paths、alias 中盡量使用【頂級標識】、【根路徑】、【絕對路徑】,不要使用【相對標識】,因為在不同深度的模塊引用時會解析為不同的路徑。
3. 【相對標識】:在哪裡被引用,相對的解析位置視被引用的地方而定,遵循當地的規則。
seajs.use 路徑解析規則
【相對標識】:相對於當前頁面解析。
define 定義模塊ID 解析規則(1)
(第3 層,路徑可以相對於alias 或paths 來設置)
可以使用:【相對標識】、【頂級標識】、【根路徑】
推薦使用【頂級標識】,如果模塊的位置不在base 基礎路徑內,則使用【相對標識】或【根路徑】。
【相對標識】:相對當前頁面解析
複製代碼代碼如下:// 代碼塊(2)
//config -- 還使用[代碼塊(1)]中的配置
// 模塊1,無歧義,根路徑解析
define("/app/src/module/Base", ..);
// 模塊2,無歧義,頂級標識,相對於base 基礎路徑來解析
define("app/src/module/Base", ..);
// 模塊3,有歧義,相對標識,此處相對於當前頁面(引用到這個模塊的html頁面)
// 但其他地方即便使用【表面上相同的“ID”】,也可能會被解析不同的模塊
define("./app/src/module/Base",..);
模塊依賴ID 解析規則(2)
(第3 層,路徑可以相對於alias 或paths 來設置)
【相對標識】:相對base 基礎路徑解析
複製代碼代碼如下://代碼塊(3)
//config -- 還使用[代碼塊(1)]中的配置
//無歧義,相對於根路徑解析
define("..", ["/app/src/module/Base"], ..)
// 無歧義,頂級標識,相對於base 基礎路徑解析
define("..", ["app/src/module/Base"], ..)
//有歧義,相對標識,此處相對於當前模塊來解析
//此處的依賴看起來是依賴於【代碼塊(2)】中的`模塊3`
//但如果當前模塊跟當前頁面不在同一層目錄下,就不會被解析為`模塊3`
define("..", ["./app/src/module/Base"],..)
模塊內require 其他模塊的ID 解析規則(3)
(第3 層,路徑可以相對於alias 或paths 來設置)
【相對標識】:相對base 基礎路徑解析
複製代碼代碼如下://代碼塊(4)
//config -- 還使用[代碼塊(1)]中的配置
define("..", [..], function(require){
//無歧義,相對於根路徑解析
require("/app/src/module/Base");
});
define("..", [..], function(require){
// 無歧義,頂級標識,相對於base 基礎路徑解析
require("app/src/module/Base");
});
define("..", [..], function(require){
//有歧義,相對標識,此處相對於當前模塊來解析
//此處的依賴看起來是依賴於【代碼塊(2)】中的`模塊3`
//但如果當前模塊跟當前頁面不在同一層目錄下,就不會被解析為`模塊3`
require("./app/src/module/Base");
})
特別提醒:模塊內三處需要寫ID的地方,不需要使用看起來相同的字符串,只要被解析為相同的模塊即可。
總結:
1.paths 和alias 的設置僅僅相當於一個變量,在哪裡使用,就在那裡替換為設定的值,然後再解析。
2.盡可能的使用【頂級標識】。
3.如果不能使用【頂級標識】,比如目錄跨越比較大等,則盡量設置alias 或paths 通過一個【非相對路徑】 標識定位到一個目錄,然後在這個標識下,再定義ID。