src/utils/ 现在有 18 个文件、2,654 行,装着四类彼此不调用的东西。它不是一个
模块,是一个命名空间;「放哪儿」这个问题在这里没有答案,所以新代码永远落在这。
四个互不相交的簇
按 import 图划分,src/utils/ 里的文件分成四组,组间几乎没有边:
| 簇 |
文件 |
谁在用 |
| Markdown 管线 |
obsidian-links.js remark-obsidian-callouts.js remark-revive-directives.js rehype-callouts.js render-markdown.js |
只有 astro.config.mjs(配置加载期)和 newsLoader |
| Vault 布局 / 文件系统 |
contentLayout.js bundleAssets.js peopleIndex.ts libraryEntries.ts |
loaders、页面、scripts |
| 双语契约 |
localized.ts i18nContract.js siteConfig.ts |
页面 / 只有 scripts / 页面 |
| 领域与展示 |
roles.ts relations.ts pageRelations.ts libraryTree.ts entrySlug.ts formatDate.ts |
页面、React 组件 |
两个具体的错位:
-
i18nContract.js(387 行,全仓最大的 util)在 src/ 下没有任何 importer。
它只被 scripts/check-content.mjs、scripts/i18n-manifest.mjs、
scripts/migrate-bundles.mjs 和它自己的测试 import。这是构建工具,住在站点
源码目录里。它的文件头注释也自己说了:三个 consumer 都是 scripts 和一份 doc。
-
五个 remark/rehype 插件(710 行)没有一个页面 import。 它们的唯一消费者是
astro.config.mjs,运行在 astro:content 存在之前。这是构建期插件,和
formatDate.ts 这种被 React 岛 import 的东西放在同一个抽屉里。
后果不只是「不好看」
页面为了拼出一个条目,要从这个抽屉里挑 5–8 个名字(见另一个 issue)。因为没有
索引、没有分组,挑哪几个只能靠读源码。这也是为什么同一个事实会存四份
(#42)——第二个人不知道第一个人把它放哪了。
../../../ 已经 113 处
tsconfig.json 没有配 paths,所以 src/pages/[lang]/*/[slug].astro 里全是:
import { entrySlug } from '../../../utils/entrySlug';
import { COLLECTION_VAULT_PATHS } from '../../../utils/contentLayout.js';
import { coverFor } from '../../../utils/bundleAssets.js';
grep -rno '\.\./\.\./\.\./' src --include='*.astro' --include='*.tsx' | wc -l → 113。
目录一动,113 处要跟着动,而这正是下面建议要做的事——所以别名应该先加。
建议
- 先加
tsconfig.json 的 paths(@/* → src/*)和 astro.config.mjs 的
vite.resolve.alias,把 113 处相对路径收掉。这一步独立,不改任何语义。
- 再按簇拆目录:
src/markdown/ ← 五个 remark/rehype 插件 + render-markdown.js
src/content-layer/ ← contentLayout bundleAssets peopleIndex
libraryEntries + 现有的 loaders/
src/i18n/ ← 已有 ui.ts,并入 localized.ts siteConfig.ts
src/domain/ ← roles relations pageRelations libraryTree
entrySlug formatDate
tools/ 或 scripts/lib/ ← i18nContract.js(它服务的是 scripts,
不是站点)
- 每个目录写一个
index.ts 作为对外的那一个入口,页面只 import 目录,不 import
目录里的具体文件。
拆完之后「这段代码放哪」这个问题有答案了,src/utils/ 应当为空并删除。
src/utils/现在有 18 个文件、2,654 行,装着四类彼此不调用的东西。它不是一个模块,是一个命名空间;「放哪儿」这个问题在这里没有答案,所以新代码永远落在这。
四个互不相交的簇
按 import 图划分,
src/utils/里的文件分成四组,组间几乎没有边:obsidian-links.jsremark-obsidian-callouts.jsremark-revive-directives.jsrehype-callouts.jsrender-markdown.jsastro.config.mjs(配置加载期)和newsLoadercontentLayout.jsbundleAssets.jspeopleIndex.tslibraryEntries.tslocalized.tsi18nContract.jssiteConfig.tsroles.tsrelations.tspageRelations.tslibraryTree.tsentrySlug.tsformatDate.ts两个具体的错位:
i18nContract.js(387 行,全仓最大的 util)在src/下没有任何 importer。它只被
scripts/check-content.mjs、scripts/i18n-manifest.mjs、scripts/migrate-bundles.mjs和它自己的测试 import。这是构建工具,住在站点源码目录里。它的文件头注释也自己说了:三个 consumer 都是 scripts 和一份 doc。
五个 remark/rehype 插件(710 行)没有一个页面 import。 它们的唯一消费者是
astro.config.mjs,运行在astro:content存在之前。这是构建期插件,和formatDate.ts这种被 React 岛 import 的东西放在同一个抽屉里。后果不只是「不好看」
页面为了拼出一个条目,要从这个抽屉里挑 5–8 个名字(见另一个 issue)。因为没有
索引、没有分组,挑哪几个只能靠读源码。这也是为什么同一个事实会存四份
(#42)——第二个人不知道第一个人把它放哪了。
../../../已经 113 处tsconfig.json没有配paths,所以src/pages/[lang]/*/[slug].astro里全是:grep -rno '\.\./\.\./\.\./' src --include='*.astro' --include='*.tsx' | wc -l→ 113。目录一动,113 处要跟着动,而这正是下面建议要做的事——所以别名应该先加。
建议
tsconfig.json的paths(@/*→src/*)和astro.config.mjs的vite.resolve.alias,把 113 处相对路径收掉。这一步独立,不改任何语义。src/markdown/← 五个 remark/rehype 插件 +render-markdown.jssrc/content-layer/←contentLayoutbundleAssetspeopleIndexlibraryEntries+ 现有的loaders/src/i18n/← 已有ui.ts,并入localized.tssiteConfig.tssrc/domain/←rolesrelationspageRelationslibraryTreeentrySlugformatDatetools/或scripts/lib/←i18nContract.js(它服务的是 scripts,不是站点)
index.ts作为对外的那一个入口,页面只 import 目录,不 import目录里的具体文件。
拆完之后「这段代码放哪」这个问题有答案了,
src/utils/应当为空并删除。