refactor: cached and reloaded file-index

This commit is contained in:
2026-03-13 15:50:50 +08:00
parent 2e04934881
commit 27bc2fc747
4 changed files with 107 additions and 134 deletions
+88
View File
@@ -0,0 +1,88 @@
/**
* 文件索引管理器
* 支持任意文件类型的索引加载和缓存
*/
type FileIndex = Record<string, string>;
let fileIndex: FileIndex | null = null;
let indexLoadPromise: Promise<void> | null = null;
/**
* 加载文件索引(只加载一次)
* 支持 CLI 环境(从 JSON 加载)和 Dev 环境(使用 webpackContext 仅加载 .md 文件)
*/
function ensureIndexLoaded(): Promise<void> {
if (indexLoadPromise) return indexLoadPromise;
indexLoadPromise = (async () => {
// 尝试 CLI 环境:从 /__FILE_INDEX.json 加载
try {
const response = await fetch("/__FILE_INDEX.json");
if (response.ok) {
const index = await response.json();
fileIndex = { ...fileIndex, ...index };
return;
}
} catch (e) {
// CLI 索引不可用时尝试 dev 环境
}
// Dev 环境:使用 import.meta.webpackContext + raw loader 加载 .md, .csv, .yarn 文件
try {
const context = import.meta.webpackContext("../../content", {
recursive: true,
regExp: /\.md|\.yarn|\.csv$/i,
});
const keys = context.keys();
const index: FileIndex = {};
for (const key of keys) {
// context 返回的是模块,需要访问其 default 导出(raw-loader 处理后的内容)
const module = context(key) as { default?: string } | string;
const content = typeof module === "string" ? module : module.default ?? "";
const normalizedPath = "/content" + key.slice(1);
index[normalizedPath] = content;
}
fileIndex = { ...fileIndex, ...index };
} catch (e) {
// webpackContext 不可用时忽略
}
})();
return indexLoadPromise;
}
/**
* 从索引获取文件内容
*/
export async function getIndexedData(path: string): Promise<string> {
await ensureIndexLoaded();
if (fileIndex && fileIndex[path]) {
return fileIndex[path];
}
const res = await fetch(path);
const content = await res.text();
fileIndex = fileIndex || {};
fileIndex[path] = content;
return content;
}
/**
* 获取指定扩展名的文件路径
*/
export async function getPathsByExtension(ext: string): Promise<string[]> {
await ensureIndexLoaded();
if (!fileIndex) return [];
const normalizedExt = ext.startsWith(".") ? ext : `.${ext}`;
return Object.keys(fileIndex).filter(path =>
path.toLowerCase().endsWith(normalizedExt.toLowerCase())
);
}
/**
* 清除索引(用于测试或重新加载)
*/
export function clearIndex(): void {
fileIndex = null;
indexLoadPromise = null;
}