上一篇提到了 NX 可以顯示專案間的依賴關係,這邊的依賴關係分兩種,project 跟 target 。
project 之間的依賴關係主要由 NX 掃描整個程式碼後分析產生,如果要在分析後的結果上增加自訂的關聯的話,要在 project.json
中定義 implicitDependencies
。
{
//...
"implicitDependencies": ["ironman-nextjs"]
}
又或者反過來想要斷開預設的關聯的話,就在專案的名稱前面加上 !
。
{
//...
"implicitDependencies" : ["!ui-react-components"]{
}
再來説說 target 的依賴關係,這裡的依賴關係主要是定義在執行這個任務之前要事先完成的任務,例如 app 依賴於 lib 的話,當要執行 app 的 build 任務的話要先確保 lib 的 build 任務是成功的。
而 target 的依賴主要定義在 target 底下的 dependsOn
當中。
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
},
這邊在 build 前面有個 ^
,算是個語法糖,代表依賴的是 dependencies
的 build 任務,完整版語法如下。
"dependsOn": [
{
"target": "build",
"projects": "dependencies"
}
]
如果沒有加上 ^
前綴的話,指的是依賴同個專案內的 target,例如 build
前要先執行 prebuild
。
"build": {
"dependsOn": ["^build", "prebuild"],
"inputs": ["production", "^production"]
},
然後雖然說依賴關係要看 dependsOn
設定,不過預設模板產生的 project.json 卻不會看到這個項目,是因為有根目錄的 nx.json
設定了預設選項 targetDefaults
。
// nx.json
{
// ...
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
}
}
}
只要 project 中有同名的 target,會在這邊定義的設定上再做延伸後執行,當然也能覆寫預設設定。
另外 target 還有個重要的設定是 inputs
,指的是要帶入這次任務的檔案有哪些。
例如在執行編譯的時候要將專案內的所有檔案納入之後進行的話,就要定義將所有檔案 input 的 glob 格式。
{
"inputs": ["{projectRoot}/**/*"]
}
NX 有設定一些關鍵字方便定義檔案的位置,像是 {projectRoot}
跟 {workspaceRoot}
。
不過這個格式太常使用了,一個個寫很麻煩,所以另外可以定義 namedInputs
來帶入常用的 glob 格式。
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": [
"default",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/jest.config.[jt]s",
"!{projectRoot}/src/test-setup.[jt]s",
"!{projectRoot}/test-setup.[jt]s",
"!{projectRoot}/.eslintrc.json",
"!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"!{projectRoot}/.storybook/**/*",
"!{projectRoot}/tsconfig.storybook.json"
],
"sharedGlobals": []
},
定義好的 namedInputs
就能直接在 target 的 inputs
使用。
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"]
},
而 input 也能像 dependsOn 一樣加上 ^
語法糖,表示依賴關係的檔案也都要納入這個任務,或是用 !
排除特定檔案。