Я использую response-stati c, чтобы скомпилировать группу страниц блога, каждая из которых написана в отдельном файле .tsx
, в сайт c. Однако я хочу иметь специальную функцию, которая заключается в автоматической генерации определенного c содержимого (например, списка ссылок, ссылочного текста) на основе дерева DOM другой страницы, но моя текущая реализация работает очень неэффективно с поток реакции c:
Например, для автоматического извлечения заголовков разделов страниц и ссылки на них:
Metadata.tsx
export type SectionMetadata = {
label: string;
title: React.ReactNode;
};
export default class Metadata {
static context = React.createContext(new Metadata());
static Provider: React.FC<{ metadata?: Metadata }> = props => (
<Metadata.context.Provider value={props.metadata || new Metadata()}>
{props.children}
</Metadata.context.Provider>
);
static extract(content: React.ReactNode) {
const metadata = new Metadata();
ReactDOMServer.renderToString(
<Metadata.Provider metadata={metadata}>{content}</Metadata.Provider>
);
return metadata;
}
sections: SectionMetadata[] = [];
registerSection = (label: string, title: React.ReactNode) => {
this.sections.push({ label, title, subsections: [] });
};
}
Section.tsx
export const Section: React.FC<{
label: string;
title: React.ReactNode;
}> = props => {
const metadata = React.useContext(Metadata.context);
const index = metadata.registerSection(props.label, props.title);
return (
<>
<h1 id={props.label}>{props.title}</h1>
{props.children}
</>
);
};
Index.tsx
type SectionData = { page: string; label: string; title: React.ReactNode };
const contents: SectionData[] = [];
const contentContext = require.context("/pages", true, /\.tsx$/, "lazy");
for (const name of contentContext.keys()) {
const label = path.basename(name, ".tsx");
contentContext(name).then(({ default: Page }: { default: any }) => {
const metadata = Metadata.extract(<Page />);
for (const sec of metadata.sections) {
contents.push({ page: label, label: sec.label, title: sec.title });
}
});
}
// Omitted some delaying mechanism that allows `contents` to be
// initialized before rendering
export default class Index extends React.Component {
render = () => (
<ul>
{contents.map((sec: SectionData, index: number) => (
<li key={index}>
<Link to={`/pages/${sec.page}#${sec.label}`}>{sec.title}</Link>
</li>
))}
</ul>
);
}
Таким образом все теги Section
, присутствующие на всех страницах, будут перехвачены и переданы в Index.tsx
для генерации списка ссылок.
Однако в настоящее время реагировать-стати c обрабатывает это как часть поведения приложения и упаковывает его в экспортируемое веб-приложение. Это означает, что каждый раз, когда клиент открывает страницу Index
, веб-приложение будет пытаться загрузить все страницы и повторно запустить логи предварительной обработки c. sh Чтобы изменить это так, чтобы в экспортированном веб-приложении динамически генерируемая часть заменялась ссылками * stati c.
Страницы моего блога состоят из специальных макетов и сред, использующих компоненты React, поэтому я приходится придерживаться одного компонента React на страницу, и будет очень сложно перейти на Markdown / plain HTML с языком шаблонов и т. д. c. Но я в порядке с переключением на Гэтсби или Далее. js, если эта функция может быть реализована там.