Предоставление токена с предварительным рендерингом Angular

#angular #server-side-rendering #angular-universal #prerender

#angular #рендеринг на стороне сервера #angular-универсальный #предварительный рендеринг

Вопрос:

Я ищу способ предоставления токенов со стороны сервера при предварительной визуализации приложения с использованием сценария предварительной визуализации.

Проблема, с которой я сталкиваюсь, связана с этой проблемой

Предоставление токенов для приложения не работает. Я даю значения в виде пустых строк, поскольку поставщики ожидают строки, которые являются: ( req.headers['user-agent'] и a string URL of the request )

  export function app(): express.Express {
      const server = express();
      const distFolder = join(process.cwd(), 'dist/web/browser');
      const indexHtml = existsSync(join(distFolder, 'index.original.html'))
        ? 'index.original.html'
        : 'index';
    
      // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
      server.engine(
        'html',
        ngExpressEngine({
          bootstrap: AppServerModule,
          providers: [
            {
              provide: UNIVERSAL_USER_AGENT,
              useValue: '',
            },
            {
              provide: UNIVERSAL_LOCATION,
              useValue: '',
            },
          ],
        })
      );
    
      server.set('view engine', 'html');
      server.set('views', distFolder);
    
      // Example Express Rest API endpoints
      // server.get('/api/**', (req, res) => { });
      // Serve static files from /browser
      server.get(
        '*.*',
        express.static(distFolder, {
          maxAge: '1y',
        })
      );
    
      // All regular routes use the Universal engine
      server.get('*', (req, res) => {
        res.render(indexHtml, {
          req,
          providers: [
            { provide: APP_BASE_HREF, useValue: req.baseUrl },
            provideLocation(req),
            provideUserAgent(req),
          ],
        });
      });
    
      return server;
    }
    
    function run(): void {
      const port = process.env['PORT'] || 4000;
    
      // Start up the Node server
      const server = app();
      server.listen(port, () => {
        console.log(`Node Express server listening on http://localhost:${port}`);
      });
    }
 

Я также предоставил токены в серверном модуле, но, тем не менее, он их не распознает.

 @NgModule({
  imports: [AppModule, ServerModule, UniversalModule, FlexLayoutServerModule],
  bootstrap: [AppComponent],
  providers: [
    {
      provide: UNIVERSAL_USER_AGENT,
      useValue: '',
    },
    {
      provide: UNIVERSAL_LOCATION,
      useValue: '',
    },
  ],
})
export class AppServerModule {}
 

Есть ли способ добиться этого? Я все еще смущен внедрением зависимостей.
Обычный SSR работает, потому что я могу предоставлять токены с использованием фабрик, поскольку они зависят от объекта req.
Но с претендентом у меня нет объекта req, поэтому я не могу использовать фабрики.
Буду признателен за любые предложения и идеи

Ответ №1:

Я использовал Scully, приложение предварительно рендерится, моя проблема решена.

Чтобы начать работу со Скалли, вы можете проверить эту ссылку.

Я заставил его работать, чтобы установить Scully с помощью Angular CLI. add Схема внесет некоторые изменения в ваш проект для базовой конфигурации, я думаю, что она также добавляет сценарии, которые я отметил ниже.

 ng add @scullyio/init
 

Затем я добавил скрипты в свой package.json файл, как показано ниже

 "scully": "npx scully --",
"scully:serve": "npx scully serve --"
 

После установки Scully мне просто нужно было создать свое приложение, используя сценарий сборки Angular: ng build и npm run scully . Это предварительно обработало мое приложение без каких-либо проблем.

Было ограничение, с которым я столкнулся для динамических маршрутов, когда у меня была конфигурация маршрута Angular, подобная /some-path/232 и 232 динамическая и неизвестная во время сборки, я обошел это ограничение, изменив этот путь маршрута на /some-path и используя queryParams для передачи данных, которые мне были нужны для маршрута / компонента. Я надеюсь, что это поможет.

Комментарии:

1. Был бы рад, если бы вы могли поделиться своим решением со Скалли

2. @HariHaran Я обновил ответ