refactor: cached and reloaded file-index
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user