angular / angular/angularfire

@angular/ssr/node not working as intended

Ouverte
#3,596 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
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

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.