Current behavior:
When using @ionic/angular-server the platform mode seems to be hardcoded to 'md'. It won’t render the specific platform mode inferred from the user agent like it does when using browser rendering.
Also, there’s no way to specify a custom mode for the IonicServerModule (something similar to the config option available with IonicModule.forRoot({...}))
Expected behavior:
Should be able to specify a mode to render the app in the IonicServerModule.
Steps to reproduce:
Scenario 1: No custom config on the IonicModule.forRoot({...})
Open Chrome dev tools and emulate an iOS device, also disable javascript (in order to properly test SSR)
The app doesn't recognize the hardcoded 'ios' mode and always renders with 'md' mode
Note: In Scenario 2 if we enable javascript to allow the transition between SSR and the browser, we first get the app with 'md' mode and then it transitions to 'ios' mode. Having an option to config the mode in the IonicServerModule would avoid this flick.
Other information:
I know there are some SSR gotchas to be aware of. There's no way to access the window object or the navigation user agent to detect the correct mode.
However there are ways to detect the user agent in the server side using for example the request user-agent headers.
By adding a way to specify the Ionic config through a provider (instead or in addition to the IonicModule.forRoot({...})) it would be possible to define the proper mode in SSR.
I'm thinking something like the APP_INITIALIZER
server.ts (option 1)
We can set a custom header in the response object and get that value in the app.module.ts using the RESPONSE injection token.
server.get('*', (req, res) => {
// Add custom header to the response we send to our Angular app. We will get this custom header in the AppModule APP_INITIALIZER
res.set('mobile-device', 'ios');
res.render(
indexHtml,
{
req,
res
}
);
});
server.ts (option 2)
Or we can override a new provider that handles the Ionic config directly in the server.ts. For this approach we would need to create a new InjectionToken for the NEW_IONIC_CONFIG.
Then in the app.module.ts we can easily get the config from the angular RESPONSE injection token or directly from the new NEW_IONIC_CONFIG token.
{
provide: APP_INITIALIZER,
useFactory: (platformId: object, response: any) => {
return () => {
// In the server.ts we added a custom response header with information about the device requesting the app
if (isPlatformServer(platformId)) {
if (response && response !== null) {
// Get custom header from the response sent from the server.ts
const mobileDeviceHeader = response.get('mobile-device');
console.log('mobileDeviceHeader', mobileDeviceHeader);
// Set Ionic config mode?
}
} else {
console.log('not server');
}
};
},
deps: [PLATFORM_ID, [new Optional(), RESPONSE]],
multi: true
}
Bug Report
Ionic version: [ ] 4.x [x] 5.x
Current behavior: When using
@ionic/angular-server
the platform mode seems to be hardcoded to'md'
. It won’t render the specific platform mode inferred from the user agent like it does when using browser rendering.Also, there’s no way to specify a custom mode for the
IonicServerModule
(something similar to the config option available withIonicModule.forRoot({...})
)Expected behavior: Should be able to specify a mode to render the app in the
IonicServerModule
.Steps to reproduce:
Scenario 1: No custom config on the
IonicModule.forRoot({...})
npm run dev:ssr
'md'
modeScenario 2: Hardcoding
'ios'
mode on theIonicModule.forRoot({...})
confignpm run dev:ssr
'ios'
mode and always renders with'md'
modeNote: In Scenario 2 if we enable javascript to allow the transition between SSR and the browser, we first get the app with
'md'
mode and then it transitions to'ios'
mode. Having an option to config themode
in theIonicServerModule
would avoid this flick.Other information: I know there are some SSR gotchas to be aware of. There's no way to access the window object or the navigation user agent to detect the correct mode.
However there are ways to detect the user agent in the server side using for example the request user-agent headers.
By adding a way to specify the Ionic config through a provider (instead or in addition to the
IonicModule.forRoot({...})
) it would be possible to define the proper mode in SSR.I'm thinking something like the
APP_INITIALIZER
server.ts (option 1)
We can set a custom header in the response object and get that value in the
app.module.ts
using theRESPONSE
injection token.server.ts (option 2)
Or we can override a new provider that handles the Ionic config directly in the
server.ts
. For this approach we would need to create a new InjectionToken for theNEW_IONIC_CONFIG
.app.modeule.ts
Then in the
app.module.ts
we can easily get the config from the angularRESPONSE
injection token or directly from the newNEW_IONIC_CONFIG
token.Ionic info:
@mhartington I know you have been working with the
IonicServerModule
. Can you point me in the right direction?