Open muradm opened 6 years ago
wow, interesting, is that work with websocket
too ? I really don't know much about ZoneMacroTaskWrapper
.
I have the same problem, that firebase cannot process in universal, because angular rendered before data come back.
can I ask, what is:
request(op: Operation): Observable<FetchResult> { return this.wrap(op); }
(line 3)
is that force to schedule by angular zone ?
can you make a simple guide, just very small to help me understand to work with some other libs ? that wil be very useful for me. please please please
Yes, that's true. Angular bootstraps when it goes stable and it is stable where there are no more Tasks running. I was working hard with Zone.js and its Tasks while fixing SSR support for apollo-angular
v0.13 and few versions before. Angular changed something between v4 and v5 and it broke apollo-angular
back then.
This is why I was soooo happy when ApolloClient 2.0 introduced ApolloLinks. This way I could use Angular's HttpClient
to make requests instead of fetch
and we got SSR support without any additional work.
Angular side of Apollo Community could create an ApolloLink that schedules Zone.js's MacroTask and completes it after execution of Links like HttpLink
, WebSocketLink
etc. This way we could reuse Link in many many cases.
Long time, still no straight forward solution for this issue :)
Here is the standalone gist which includes AngularSchemaLink
. May be some one could add another package like apollo-angular-link-schema
Basically it can be used like:
In backend main.ts
provide the schema and context values:
// main.ts
app.get('*', (req, res) => {
res.render(
'index.html',
{
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
{ provide: 'SSR_GRAPHQL_SCHEMA', useValue: context.schema },
{ provide: 'SSR_GRAPHQL_CONTEXT', useValue: context }
],
url: req.url,
document: fs.readFileSync('./dist/browser/index.html'),
req,
res
}
)
})
And in AppServerModule
configure Apollo:
@NgModule({
imports: [
AppModule,
ServerModule,
NoopAnimationsModule,
FlexLayoutServerModule,
// ....
ModuleMapLoaderModule
],
bootstrap: [AppComponent],
providers: [
// ...
{
provide: APOLLO_OPTIONS,
useFactory: (schema: GraphQLSchema, context: any) => {
return {
cache: new InMemoryCache(),
link: new AngularSchemaLink({ schema, context })
}
},
deps: ['SSR_GRAPHQL_SCHEMA', 'SSR_GRAPHQL_CONTEXT']
}
]
})
export class AppServerModule {}
TransferState
can be used for SSR features of Apollo as well.
@hiepxanh, for line 3, you may look into gist above. As mentioned before it relays on adapted copy paste of ZoneMacroTaskWrapper
from @angular/platform-server
. Basically utility class to wrap some observable into Zone.js task.
For websockets... What is websocket? Connection established from client browser to server. Whole point of using SchemaLink
is to avoid unnecessary round trips when application is being rendered server side. Let's imagine that websocket we have application which uses websocket, how it should suppose to behave when rendered on server side? probably such actions would be guarded with something like isPlatformBrowser()
. I.e. just don't make websocket subscriptions when being rendered server side. Websocket is long lived thing, how would one shot render process complete?
Server side Angular allows to render on server. If angular
ServerAppModule
and GraphQL server are running in same process, it could be possible to shortcut GraphQL calls without additional HTTP round-trip, like this:Then at
ServerAppModule
bootstrap:Then without any change in Angular application we get local calls to GraphQL server.
However this does not work out of the box, because
SchemaLink
resolves toPromise
outside of angular zone, so that rendering ends before GrahpQLexecute
finished.In order to do it properly, one has to execute
execute
call as zone macro task, like explained here. Then you can't useSchemaLink
as provided by Apollo.Suggestion is to provide
AngularSchemaLink
byapollo-angular
for universal server which properly schedulesexecute
calls.For now, the following works:
Then you can use it in place of
SchemaLink
:Then your
ServerAppModule
will properly render without doing HTTP calls.