摘要:在寫大型項目的時候一不小心就會踩到直接循環依賴的坑里面所謂直接循環依賴是指在模塊工廠函數中對其它依賴于自己的模塊的成員有直接調用的情況比如假設有兩個模塊和其中的內容如下的內容如下下面這一行導致了直接循環依賴這時執行會報的錯誤這是因為模塊的工
在寫大型項目的時候, 一不小心就會踩到直接循環依賴的坑里面, 所謂直接循環依賴, 是指在模塊工廠函數中, 對其它依賴于自己的模塊的成員有直接調用的情況. 比如:
假設有兩個模塊 a.js 和 b.js, 其中 a.js 的內容如下:
const b = require("./b") exports.hello_a = function hello_a() { return "a" } exports.hello_from_b = function hello_from_b() { return b.hello_b() }
b.js 的內容如下:
const a = require("./a") // 下面這一行導致了直接循環依賴 exports.hello_from_a = a.hello_a() exports.hello_b = function hello_b() { return "b" }
這時, 執行 a.js, 會報 TypeError: a.hello_a is not a function 的錯誤, 這是因為模塊 a.js 的工廠函數還在執行, 并且 hello_a 函數的聲明尚未被執行, 而 b.js 就直接調用了 a.hello_a, 所以這個變量當成不存在, 也就報錯了, 如果這不是一個函數而是一個變量, 則不會報錯, 只是獲取到的值為 undefined, 這種情況會更難定位問題.
雖然現在有一個項目叫 madge 可以用來定位循環依賴, 但是這個倉庫在處理 TypeScript 的時候的輸出簡直就是個玄學問題, 會常常莫名其妙的忽略掉了不應該被忽略掉的文件, 這個問題后面我會舉例說明.
所以我花了一天的時間來造了一個輪子: dpdm, 專門用來檢測 JavaScript 和 TypeScript 項目中的循環依賴, 其目前可以檢測下面這四種情況:
CommonJS 的 require(...) 函數調用
ESM 的靜態 import ... from ... 語句
ESM 的動態 import(...) 函數調用
ESM 的靜態 export ... from ... 語句
能滿足大多數情況的需要, 因為現在極少有人有用 AMD 和 System 了.
使用方式
安裝: dpdm 可以在命令行或者 js 項目中使用, 如果想在命令行使用(推薦), 則建議全局安裝, 否則安裝到你的項目中即可
# 全局安裝 npm i -g dpdm # 或者用 yarn: yarn global add dpdm # 項目目錄中安裝 npm i dpdm # 或者用 yarn: yarn add dpdm
在命令行中使用: 直接使用命令 dpdm [可選參數] <入口文件> 即可, 輸出示例:
默認情況下會輸出依賴樹(tree), 循環依賴列表(circular), 以及警示信息(warning), 你可以使用參數關閉掉其中任意項, 比如 dpdm --tree false --warning false ./src/index.ts 來關閉依賴樹和警示信息(僅展示循環依賴表).
可以使用 --output
默認情況下忽略了 node_modules 中的內容, 可以使用 --exclude "" 來取消忽略
使用 --help 查看完整的幫助文檔:
dpdm --help dpdm [] entry... Options: --version Show version number [boolean] --context the context directory to shorten path, default is process.cwd() [string] --extensions, --ext comma separated extensions to resolve [string] [default: ".ts,.tsx,.mjs,.js,.jsx,.json"] --include included filenames regexp in string [string] [default: ".m?[tj]sx?$"] --exclude excluded filenames regexp in string [string] [default: "/node_modules/"] --output, -o output json to file [string] --tree print tree to stdout [boolean] [default: true] --circular print circular to stdout [boolean] [default: true] --warning print warning to stdout [boolean] [default: true] -h, --help Show help [boolean]
在代碼中使用: dpdm 提供了若干 API, 具體可以查看包中提供的 .d.ts 提供的定義, 或者到 GitHub 查看文檔:
比如:
import { parseCircular, parseDependencyTree, parseWarnings, prettyCircular, prettyTree, prettyWarning, } from "dpdm"; parseDependencyTree(["./src/**/*"] /* 入口, glob 匹配, 可以是數組 */, { /* 參數列表, 下面這些是默認參數 */ context: process.cwd(), // 前綴, 用來簡寫文件名 extensions: ["", ".ts", ".tsx", ".mjs", ".js", ".jsx", ".json"], // 后綴 include: /.m?[tj]sx?$/, // 需要解析的文件 exclude: //node_modules//, // 需要忽略的文件 }).then((tree) => { console.log("Tree:"); console.log(prettyTree(tree, Object.keys(tree))); console.log(""); console.log("Circular:"); console.log(prettyCircular(parseCircular(tree))); console.log(""); console.log("Warning:"); console.log(prettyWarning(parseWarnings(tree))); });提問題
項目在 GitHub 已開源, 地址是 https://github.com/acrazing/dpdm, 你可以到上面提 issue 或者提交 pr.
順便, 求贊~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105791.html
摘要:自動化接入和升級方案通過命令行工具提供一鍵接入升級能力,同時集成到團隊腳手架中,大大降低了工程接入和維護的成本。原始代碼經過解析器的解析,在管道中逐一經過所有規則的檢查,最終檢測出所有不符合規范的代碼,并輸出為報告。 引言 代碼規范是軟件開發領域經久不衰的話題,幾乎所有工程師在開發過程中都會遇到,并或多或少會思考過這一問題。隨著前端應用的大型化和復雜化,越來越多的前端工程師和團隊開始重...
摘要:例如允許的對象默認情況下,通過使用內置宏將核心對象和方法映射到。例如這被轉換為以下代碼類可以定義構造函數,具有超類,并且可以像在中一樣實例化。因此,它不違反原則。用于聲明該對象可以用作構造函數。 這個工具可以將java代碼轉為js代碼,從而可以使用java編寫前端代碼 如果排版看著費勁可以下載下方html,打開html后使用google翻譯 JSweet語言規范版本:2.x(快照) 作...
摘要:例如允許的對象默認情況下,通過使用內置宏將核心對象和方法映射到。例如這被轉換為以下代碼類可以定義構造函數,具有超類,并且可以像在中一樣實例化。因此,它不違反原則。用于聲明該對象可以用作構造函數。 這個工具可以將java代碼轉為js代碼,從而可以使用java編寫前端代碼 如果排版看著費勁可以下載下方html,打開html后使用google翻譯 JSweet語言規范版本:2.x(快照) 作...
閱讀 2418·2023-04-26 00:46
閱讀 581·2023-04-25 21:36
閱讀 729·2021-11-24 10:19
閱讀 2266·2021-11-23 09:51
閱讀 1015·2021-10-21 09:39
閱讀 830·2021-09-22 10:02
閱讀 1664·2021-09-03 10:29
閱讀 2677·2019-08-30 15:53