Я не могу понять, как заставить это работать без использования теневых магических волшебников, так что, возможно, я что-то упускаю.
Мой пример случая:
У меня есть простое приложение Angular 18 SSR с маршрутом домой и пользователем/:имя пользователя.
Я не хочу запрашивать свою базу данных со своего веб-сайта, поэтому мне нужно заранее получить информацию обо всех своих пользователях и соответствующим образом сгенерировать маршруты.
Если я получу эти данные пользователей:
{ name: 'alice', email: '[email protected]' },
{ name: 'bob', email: '[email protected]' },
{ name: 'charlie', email: '[email protected]' },
Я хочу, чтобы Angular SSR создавал мой сайт с маршрутами:
Я пробовал добавлять их динамически вот так
addUserRoutes(users: any[]) {
const newRoutes = users.map(user => ({
path: 'user/' + user.name,
component: UserComponent,
resolve: { user: user },
}));
this.router.resetConfig([...this.router.config, ...newRoutes]);
}
Если я распечатаю файл router.config, я получу все нужные маршруты, но SSR не сгенерировал их, поэтому я не могу найти их на своем веб-сайте, поэтому это решение не работает.
Я пытался получить данные до начальной загрузки
export function initializeApp(http: HttpClient) {
return (): Promise<any> =>
firstValueFrom(
http
.get('generated/db-data.json')
.pipe(
map((data: any) => data.users),
));
}
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideClientHydration(),
provideAngularSvgIcon(),
provideHttpClient(),
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
multi: true,
deps: [HttpClient],
},
]
};
Но тогда я не знаю, как использовать этих пользователей для обновления моего массива маршрутов в моем ProvideRouter(routes).
Я собираюсь просто использовать данные из InitializeApp напрямую для динамического создания массива маршрутов и попытаться использовать его напрямую, обновляя в ProvideRouter(routes).
Обновлено: я обсуждаю это со своими коллегами, и на самом деле моя база данных на самом деле представляет собой большой json, и я перестану выполнять асинхронные вызовы и буду заниматься внедрением зависимостей и т. д., и просто
import userData from '../../public/generated/db-data.json';
function generateRoutes(): Routes {
const userRoutes = userData.users.map(user => ({
path: 'user/' + user.name,
component: UserComponent,
data: { user },
}));
return [
...userRoutes,
];
Нет, если данные изменились, мы можем их повторно развернуть, веб-сайт должен быть оптимизирован для единого входа, чтобы он был статичным везде, где это возможно. На данный момент это мой вариант использования, но я согласен с вами. Если бы я хотел, чтобы профили пользователей обновлялись часто, я бы использовал внешний API
Лучшее решение — использовать параметризованные маршруты предварительной визуализации, где вы указываете, какие маршруты вы хотите предварительно визуализировать, а затем SSR визуализирует эти маршруты как статические маршруты, и не будет ненужных вызовов API для получения пользователей во внешнем интерфейсе.
Сначала вам нужно настроить параметризованный маршрут, например user/:username
или что-то в этом роде.
Затем вы можете написать сценарий, который генерирует routes.txt
из вызова API, который получает список пользователей из БД, затем при сборке приложения файл Routes.txt обрабатывается, и вы получаете желаемый результат.
Этот скрипт будет обработан приложением Angular перед запуском npm run start
или npm run build
.
...
"start": "node dynamic-routes.js && ng serve",
"build": "node dynamic-routes.js && ng build",
...
О боже, я полностью уклоняюсь от этой части документации... Спасибо. Но теперь мне интересно, как передать все мои пользовательские данные маршруту. В документации можно определить маршрут, но я также хочу, чтобы маршрут содержал весь мой пользовательский объект. в качестве данных. Может быть, что-то вроде /products/1?name=charlie&[email protected] /products/555?name=marie&[email protected]
@TheSegfault Да, вы можете выполнить вызов API ngOnInit
, который извлекает данные, затем Angular SSR предварительно отобразит HTML с помощью этого вызова API и заполнит HTML, чтобы HTML мог видеть все данные во время сканирования веб-страниц.
Большое спасибо, SSR достаточно умен, чтобы использовать то, что он находит в ngOnInit каждого маршрута, и совершать вызов, это потрясающе!
Что, если данные пользователя будут изменены пользователями, без вызова API на бэкэнд, как вы узнаете, изменились ли они, разве динамические маршруты, такие как
/user/:username
, не являются лучшим решением для вас!