ionic-framework
ionic-framework copied to clipboard
bug: angular, mode always md when doing ssr
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 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({...})
- Enable (SSR with Angular Universal And Ionic)[https://ionicframework.com/blog/ssr-with-angular-universal-and-ionic/]
- Run
npm run dev:ssr
- Open Chrome dev tools and emulate an iOS device
- The app doesn't recognize the iOS device and always renders with
'md'
mode
Scenario 2: Hardcoding 'ios'
mode on the IonicModule.forRoot({...})
config
- Enable (SSR with Angular Universal And Ionic)[https://ionicframework.com/blog/ssr-with-angular-universal-and-ionic/]
- Run
npm run dev:ssr
- 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
.
server.get('*', (req, res) => {
res.render(
indexHtml,
{
req,
res,
providers: [
{
provide: NEW_IONIC_CONFIG,
useValue: {
mode: 'ios'
}
}
]
}
);
});
app.modeule.ts
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
}
Ionic info:
Ionic:
Ionic CLI : 6.11.8 (/Users/agustin/.npm-global/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 5.3.3
@angular-devkit/build-angular : 0.1001.2
@angular-devkit/schematics : 10.1.2
@angular/cli : 10.1.2
@ionic/angular-toolkit : 2.3.3
Capacitor:
Capacitor CLI : 2.4.1
@capacitor/core : 2.4.1
Utility:
cordova-res (update available: 0.15.1) : 0.11.0
native-run : not installed
System:
NodeJS : v12.14.1 (/usr/local/bin/node)
npm : 6.14.8
OS : macOS Catalina
@mhartington I know you have been working with the IonicServerModule
. Can you point me in the right direction?
Same issue here... did you ever find a solution?
We are also facing the same problem. Is there any solution for this?