angular docs: describe how to create server-side only services

bt1cpqcv  于 6个月前  发布在  Angular
关注(0)|答案(9)|浏览(59)

与功能请求相关的@angular/*包?

platform-browser, platform-server

描述

作为一名开发者,我需要一个仅在服务器端注入和执行的服务,因为它在请求URL中包含一个连接令牌。

建议的解决方案

要定义可注入参数,您可以定义一个平台,您希望服务在其中可注入:服务器或浏览器

考虑过的替代方案

目前我正在使用StateTransfer来提供数据,但仍然存在一个带有安全令牌的浏览器捆绑包中的服务,在那里我公开了一个令牌

rjzwgtxy

rjzwgtxy1#

你好,@imaksp。我感谢你的建议,但这里有几个问题。

  1. 异步输入应该在组件加载之前在解析器中完成。ngOninit 默认情况下不会等待异步操作,即使你把它放在前面。

  2. 我不是调用一个端点,我想在第一次加载时直接从服务器加载数据,而不是调用另一个端点。

  3. 如果使用 isPlatformServer ,它会将仅存在于服务器的数据添加到客户端应用程序中。这不仅是一个安全问题,还会给我的客户端包带来不必要的开销。

但是这篇帖子是关于在解析器(或提供者)中加载文档的,仅限于从服务器加载并在服务器和浏览器版本上可用的内容。让 transferState 从解析器中自动加载任何内容也应该是自动完成的,但这是另一个问题。

bfhwhh0e

bfhwhh0e2#

是的,如果你不使用端点,那么一些代码可能会被暴露出来,但是如果是API服务器代码,就不会被暴露。服务器上只有环境变量中的密钥可以用于API。

我认为在这里,像next.js的getServerSideProps或getStaticProps这样的函数会更合适。类似于仅在服务器上解析路由的函数。

svujldwt

svujldwt3#

这是目前已经可以通过使用DI并根据平台提供不同的提供者来实现的。

data-service.service.ts

import { Injectable } from '@angular/core';

@Injectable()
export abstract class DataServiceService {
  abstract get(id: string): string
}

export class DataServiceServiceServer extends DataServiceService {
   get(id: string): string {
    return 'server-data-performed-with-secret-tokens';
   }
}

export class DataServiceServiceBrowser extends DataServiceService {
  get(id: string): string {
   return 'browser-data';
  }
}

app.config.server.ts

const serverConfig: ApplicationConfig = {
  providers: [
    provideServerRendering(),
    {
      provide: DataServiceService,
      useClass: DataServiceServiceServer
    }
  ]
};

app.config.ts

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideClientHydration(),
    {
      provide: DataServiceService,
      useClass: DataServiceServiceBrowser,
    },
  ],
};
um6iljoc

um6iljoc4#

这看起来像是文档的一个很好的补充,我正在更新工单标题以反映这一点。

ltskdhd1

ltskdhd15#

这个状态没有转移。我们应该在这个上面使用$x_1^m_n^x$吗?如何在不替换浏览器版本的情况下使服务器数据得到充分的呈现?

hpcdzsge

hpcdzsge6#

我尝试使用DI,但是在bootstrap之前无法运行useState:
https://github.com/jdgamble555/angular-state-test
我们需要一种传输状态的方法。

hivapdat

hivapdat7#

使用APP_INITIALIZER成功实现。
https://dev.to/jdgamble555/preloading-data-in-angular-universal-20lj
J
这真的应该是某种预先制作的提供者。

oewdyzsn

oewdyzsn8#

@alan-agius4 - I keep coming back to this. I don't want to load the same service on every route, some routes may have a specific service.

How would you do this per route?

If I use this method on the server, it will not get populated.

const serverConfig: ApplicationConfig = {
  providers: [
    provideServerRendering(),
    provideRouter(
      [
        {
          path: '',
          component: SomeComponent,
          resolve: { data: SomeResolver },
          providers: [
            {
              provide: DataServiceService,
              useClass: DataServiceServiceServer
            }
         ]
        }
      ]
    )
  ]
};

export const config = mergeApplicationConfig(serverConfig, appConfig);

I would think I would use the resolver to call a server service, then use the abstract for the browser version, but this will not work as the useClass never gets triggered.
This should be updated in the docs with a way to do this for the whole app AND some way to do this per route.
J

oyjwcjzk

oyjwcjzk9#

Hi @jdgamble555 ,我同意在路由级别应该有一些适当的方法来实现这个功能。但是我认为,如果你只是通过检查isPlatformServer并在ngOnInit中调用服务器服务,然后将返回数据保存在transfer状态中,那么它应该在客户端很容易获取,并且Angular也应该自动缓存这个服务响应在服务器上。
& 我还认为在路由级别应该有更明确的方法来设置transfer状态。

相关问题