@angular/ssr/node not working as intended
- Langage dominant
- TypeScript
- Étoiles
- 7.8k
- Forks
- 2.2k
- Merge moyen
- 22 h 28 min
- PR mergées (30 j)
- 6
Description
I am using @angular/fire@19.0.0-rc.4, and I have the following:
`src/server.ts`
>import {
> AngularNodeAppEngine,
> createNodeRequestHandler,
> isMainModule,
> writeResponseToNodeResponse,
>} from "@angular/ssr/node";
>
>import express from "express";
>
>import { dirname, resolve } from "node:path";
>import { fileURLToPath } from "node:url";
>
>const serverDistFolder = dirname(fileURLToPath(import.meta.url));
>const browserDistFolder = resolve(serverDistFolder, "../browser");
>
>const server = express();
>const angularNodeAppEngine = new AngularNodeAppEngine();
>
>server.use(
> express.static(browserDistFolder, {
> maxAge: "1y",
> index: false,
> redirect: false,
> }),
>);
>
>server.use("/**", (serverRequest, serverResponse, serverNextFunction) => {
> angularNodeAppEngine
> .handle(serverRequest)
> .then((response) => {
> if (response) {
> return writeResponseToNodeResponse(response, serverResponse);
> } else {
> return serverNextFunction();
> }
> })
> .catch(serverNextFunction);
>});
>
>if (isMainModule(import.meta.url)) {
> const port = process.env["PORT"] || 4000;
> server.listen(port, () => {
> console.log(``Node Express server listening on http://localhost:${port}``);
> });
>}
>
>export const reqHandler = createNodeRequestHandler(server);
`src/app/app.routes.ts`
>import { Route } from "@angular/router";
>
>import { ErrorComponent } from "./error/error.component";
>import { errorResolver } from "./error/error.resolver";
>import { HomeComponent } from "./home/home.component";
>import { homeResolver } from "./home/home.resolver";
>
>export const routes: Route[] = [
> {
> path: "error",
> component: ErrorComponent,
> resolve: {
> error: errorResolver,
> },
> },
> {
> path: "",
> pathMatch: "full",
> component: HomeComponent,
> resolve: {
> home: homeResolver,
> },
> },
> {
> path: "**",
> redirectTo: "/error",
> },
>];
`src/app/app.routes.server.ts`
>import { RenderMode, ServerRoute } from "@angular/ssr";
>
>export const serverRoutes: ServerRoute[] = [
> {
> path: "**",
> renderMode: RenderMode.Server,
> },
>];
`src/app/app.config.ts`
>import {
> ApplicationConfig,
> provideExperimentalZonelessChangeDetection,
>} from "@angular/core";
>import { initializeApp, provideFirebaseApp } from "@angular/fire/app";
>import { getAnalytics, provideAnalytics } from "@angular/fire/analytics";
>import { getFirestore, provideFirestore } from "@angular/fire/firestore";
>import { getStorage, provideStorage } from "@angular/fire/storage";
>import {
> provideClientHydration,
> withEventReplay,
>} from "@angular/platform-browser";
>import {
> provideRouter,
> withEnabledBlockingInitialNavigation,
> withInMemoryScrolling,
>} from "@angular/router";
>
>import { routes } from "./app.routes";
>
>import { environment } from "../environments/environment.production";
>
>export const appConfig: ApplicationConfig = {
> providers: [
> provideExperimentalZonelessChangeDetection(),
> provideClientHydration(withEventReplay()),
> provideRouter(
> routes,
> withEnabledBlockingInitialNavigation(),
> withInMemoryScrolling({
> anchorScrolling: "enabled",
> scrollPositionRestoration: "enabled",
> }),
> ),
> provideFirebaseApp(() => {
> return initializeApp(environment.firebase);
> }),
> provideAnalytics(() => {
> return getAnalytics();
> }),
> provideFirestore(() => {
> return getFirestore();
> }),
> provideStorage(() => {
> return getStorage();
> }),
> ],
>};
`src/app/app.config.server.ts`
>import { mergeApplicationConfig, ApplicationConfig } from "@angular/core";
>import { provideServerRendering } from "@angular/platform-server";
>import { provideServerRoutesConfig } from "@angular/ssr";
>
>import { appConfig } from "./app.config";
>import { serverRoutes } from "./app.routes.server";
>
>const serverConfig: ApplicationConfig = {
> providers: [
> provideServerRendering(),
> provideServerRoutesConfig(serverRoutes),
> ],
>};
>
>export const config = mergeApplicationConfig(appConfig, serverConfig);
Now, I am not using `ng deploy` or `firebase deploy` since they require `@angular-devkit/build-angular` and the SSR function being deployed is not working. Instead, I created a separate Firebase Repo and initialised both hosting and functions.
`firebase.json`
>{
> "functions": [
> {
> "source": "functions/ssr",
> "codebase": "ssr",
> "ignore": [...]
> }
> ],
> "hosting": {
> "public": "hosting",
> "ignore": [...],
> "rewrites": [
> {
> "source": "**",
> "function": {
> "functionId": "ssr",
> "region": "europe-west1"
> }
> }
> ]
> }
>}
`functions/ssr/index.js`
>import { onRequest } from "firebase-functions/v2/https";
>
>import { reqHandler } from "./build/template/server/server.mjs";
>
>export const ssr = onRequest(
> {
> region: "europe-west1",
> invoker: "public",
> memory: "256MiB",
> cpu: 1,
> timeoutSeconds: 60,
> concurrency: 80,
> minInstances: 1,
> maxInstances: 100,
> ingressSettings: "ALLOW_ALL",
> preserveExternalChanges: false,
> },
> reqHandler,
>);
In the Firebase Repo, I am successfully deploying both hosting and functions using `firebase deploy`. The SSR function works, save for paths redirected to the ErrorComponent:
`src/app/app.routes.ts`
> {
> path: "**",
> redirectTo: "/error",
> },
When seeing the Google Cloud Console logs for the Cloud function, the express instance is giving a 302 response (which is what you'd expect from a redirect), however, instead of staying on port 80, the redirect URL is given on port 8080, which is the internal port being using by the express instance. I reckon that server.ts needs to be modified, however, I don't know how.
Guide de contribution
Ouvrir le guide de contribution
Piste de recherche
Commencez par src/server.ts et functions/ssr/index.js, puis comparez la redirection de la route /error dans src/app/app.routes.ts avec la requête Firebase Hosting déployée. Inspectez la réponse 302 Location de la Cloud Function et vérifiez que le comportement final conserve l’URL Hosting publique au lieu d’exposer le port 8080.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- angular, express, firebase, node.js, typescript
- Domaine
- backend, cloud, web-dev
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 38/100