ionic-team / ionic-team/ionic-framework

bug: angular, mode always md when doing ssr

Abierto
#22,121 2 comentarios 1 reacción 0 asignados Ver en GitHub
package: angular type: bug
Lenguaje dominante
TypeScript
Estrellas
52.7k
Forks
13.3k
Merge medio
1 d 15 h
PR fusionados (30 d)
51

Descripción

# 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({...})`
1. Enable (SSR with Angular Universal And Ionic)[https://ionicframework.com/blog/ssr-with-angular-universal-and-ionic/]
2. Run `npm run dev:ssr`
3. Open Chrome dev tools and emulate an iOS device
4. The app doesn't recognize the iOS device and always renders with `'md'` mode

**Scenario 2:** Hardcoding `'ios'` mode on the `IonicModule.forRoot({...})` config
1. Enable (SSR with Angular Universal And Ionic)[https://ionicframework.com/blog/ssr-with-angular-universal-and-ionic/]
2. Run `npm run dev:ssr`
3. Open Chrome dev tools and emulate an iOS device, also disable javascript (in order to properly test SSR)
4. 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.
``` typescript
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`.
``` typescript
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.
``` typescript
{
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`](https://github.com/ionic-team/ionic-framework/blob/master/packages/angular-server/src/ionic-server-module.ts). Can you point me in the right direction?

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.