Open Ozzcer opened 10 months ago
@alan-agius4 https://github.com/BeCaDRI/angular-ssr-demo Checkout
npm i
ng build
npm run serve:ssr:angular_ssr
Open http://localhost:4000/?email=test@test.com&name=user
Check node console => queryparams are there Check Browser DEV Consolte => queryparams are null
Hello @BeCaDRI, it seems this isn't the appropriate issue for addressing your concern. Nevertheless, according to your reproduction, the functionality appears to be working correctly as expected because QUERYPARAMS
is configured solely within the server application. Additionally, it's advisable to utilize the router for accessing query parameters in general: https://angular.io/api/router/ActivatedRoute
@alan-agius4 Router Params are simply used to have some input example (and it does not affect how we want to inject data from the server to the client). And the idea was to inject some token which is used by the node server to get detailed data from another backend before rendering the page (based on the query params/other calls). Or it is a general misunderstanding, that the rendering is not done at runtime?
So how is it possible to use providers in production? Target is to provide data from the server while using SSR without using an extra API call.
I still don't see why this is not an issue, other users have the same problem https://github.com/angular/angular-cli/issues/26323#issuecomment-1859954143
As the documentation is non-existent for SSR providers for Angular 17 and any idea I have found here or on the Internet so far hasn't worked it is frustrating to get a simple task done.
Sorry for poking around here, but if there is a solution I don't see/find it Thanks for feedback anyway!
@BeCaDRI, DI and provider tokens values will not be sent from the server to the client. DI functions identically on both the server and client applications, so there's no specific documentation for server-side DI.
For data transfer from the server to the browser application, you should utilize the TransferState API.
@alan-agius4 Transferstate was my first approach which didn't work either. I'll try again, thanks all.
I think the quickest path forward that would unblock a majority of people is injecting Request
properly during the Vite builder SSR, as this is how most apps are going to be accessing cookies, and cookies are basically the only way to do any sort of authenticated SSR.
Beyond that, even if full custom server.ts
support isn't feasible at this time, registering custom middlewares in some way would handle basically every other use case.
Side note @alan-agius4 as you may have some insight here:
I would work on a PR for this myself but I cannot run an clean npm install
in the parent workspace of the CLI repo or the build_angular
package without either peer dep errors or a missing package.json
that the installer is trying to grab from the cache.
Indeed, several things about SSR need to be documented, for example since the move from @nguniversal/express-engine to @angular/ssr the express tokens were lost:
I had to search the internet for a while to understand that I had to add the "src/express.tokens.ts" file now because it no longer comes in the @angular/ssr package, so I wrote the file manually and found another problem:
The REQUEST and RESPONSE are undefined when you inject:
@Optional() @Inject(RESPONSE) private response: Response
I have published a repo with the minimum to recreate the SSR problem with angular 17: https://github.com/hittten/angularSSR17
git clone https://github.com/hittten/angularSSR17
npm install
npm start
Navigate to http://localhost:4200/404
ERROR TypeError: Cannot read properties of null (reading 'status')
at _NotFoundPageComponent (/Workspace/hittten/angularSSR17/src/app/pages/not-found-page/not-found-page.component.ts:17:21)
import {RESPONSE} from "@nguniversal/express-engine/tokens";
import {Response} from "express";
constructor(
@Optional() @Inject(RESPONSE) private response: Response,
@Inject(PLATFORM_ID) private platformId: object,
) {
if (isPlatformServer(this.platformId)) {
this.response.status(404)
} else {
console.error(`response status code 404`)
}
}
import { InjectionToken } from '@angular/core';
import { Request, Response } from 'express';
const REQUEST = new InjectionToken<Request>('REQUEST');
const RESPONSE = new InjectionToken<Response>('RESPONSE');
constructor(
@Optional() @Inject(RESPONSE) private response: Response,
@Inject(PLATFORM_ID) private platformId: object,
) {
if (isPlatformServer(this.platformId)) {
this.response.status(404)
} else {
console.error(`response status code 404`)
}
}
basically I have created a project like this:
npx @angular/cli@17.0.8 new angularSSR17 --ssr --routing --scss --skip-tests
cd angularSSR17
npm i -D firebase-tools@13.0.2
ng g c pages/homePage
ng g c pages/aboutPage
ng g c pages/notFoundPage
I also disable pre-render in angular.json:
{
"scripts": [],
"server": "src/main.server.ts",
"prerender": false,
"ssr": {
"entry": "server.ts"
}
}
and I have done the settings of the routes for lazy load. I have not installed @angular/fire because it is not necessary to recreate the SSR error.
I also intent to provide express tokens in /server.ts: provide: REQUEST, useValue: req }, { provide: RESPONSE, useValue: res }, which is not necessary to do in angular 16, but it doesn't work either.
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [
{ provide: APP_BASE_HREF, useValue: baseUrl },
{ provide: REQUEST, useValue: req },
{ provide: RESPONSE, useValue: res },
],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
Angular CLI: 17.0.8
Node: 20.10.0
Package Manager: npm 10.2.5
OS: darwin arm64
Angular: 17.0.8
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router, ssr
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1700.8
@angular-devkit/build-angular 17.0.8
@angular-devkit/core 17.0.8
@angular-devkit/schematics 17.0.8
@schematics/angular 17.0.8
rxjs 7.8.1
typescript 5.2.2
zone.js 0.14.2
@hittten perhaps you are missing the file that the migrations create for you:
https://stackoverflow.com/a/77459798
I had the same problem but looking around I found it. I haven’t seen that in the docs though and in my view it should be created by default when you select SSR enabled
@hittten perhaps you are missing the file that the migrations create for you:
https://stackoverflow.com/a/77459798
I had the same problem but looking around I found it. I haven’t seen that in the docs though and in my view it should be created by default when you select SSR enabled
I
Indeed, several things about SSR need to be documented, for example since the move from @nguniversal/express-engine to @angular/ssr the express tokens were lost:
I had to search the internet for a while to understand that I had to add the "src/express.tokens.ts" file now because it no longer comes in the @angular/ssr package and that's what I did
I have published a repo with the minimum to recreate the SSR problem with angular 17: https://github.com/hittten/angularSSR17
Clone & Setup:
git clone https://github.com/hittten/angularSSR17 npm install npm start
Log
Navigate to http://localhost:4200/404
ERROR TypeError: Cannot read properties of null (reading 'status') at _NotFoundPageComponent (/Workspace/hittten/angularSSR17/src/app/pages/not-found-page/not-found-page.component.ts:17:21)
Angular 16 code (working):
import {RESPONSE} from "@nguniversal/express-engine/tokens"; import {Response} from "express"; constructor( @Optional() @Inject(RESPONSE) private response: Response, @Inject(PLATFORM_ID) private platformId: object, ) { if (isPlatformServer(this.platformId)) { this.response.status(404) } else { console.error(`response status code 404`) } }
Angular 17 code (not working):
import { InjectionToken } from '@angular/core'; import { Request, Response } from 'express'; const REQUEST = new InjectionToken<Request>('REQUEST'); const RESPONSE = new InjectionToken<Response>('RESPONSE'); constructor( @Optional() @Inject(RESPONSE) private response: Response, @Inject(PLATFORM_ID) private platformId: object, ) { if (isPlatformServer(this.platformId)) { this.response.status(404) } else { console.error(`response status code 404`) } }
Info
basically I have created a project like this:
npx @angular/cli@17.0.8 new angularSSR17 --ssr --routing --scss --skip-tests cd angularSSR17 npm i -D firebase-tools@13.0.2 ng g c pages/homePage ng g c pages/aboutPage ng g c pages/notFoundPage
I also disable pre-render in angular.json:
{ "scripts": [], "server": "src/main.server.ts", "prerender": false, "ssr": { "entry": "server.ts" } }
and I have done the settings of the routes for lazy load. I have not installed @angular/fire because it is not necessary to recreate the SSR error.
And...
I also intent to provide express tokens in /server.ts: provide: REQUEST, useValue: req }, { provide: RESPONSE, useValue: res }, which is not necessary to do in angular 16, but it doesn't work either.
server.get('*', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap, documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: browserDistFolder, providers: [ { provide: APP_BASE_HREF, useValue: baseUrl }, { provide: REQUEST, useValue: req }, { provide: RESPONSE, useValue: res }, ], }) .then((html) => res.send(html)) .catch((err) => next(err)); });
Versions
Angular CLI: 17.0.8 Node: 20.10.0 Package Manager: npm 10.2.5 OS: darwin arm64 Angular: 17.0.8 ... animations, cli, common, compiler, compiler-cli, core, forms ... platform-browser, platform-browser-dynamic, platform-server ... router, ssr Package Version --------------------------------------------------------- @angular-devkit/architect 0.1700.8 @angular-devkit/build-angular 17.0.8 @angular-devkit/core 17.0.8 @angular-devkit/schematics 17.0.8 @schematics/angular 17.0.8 rxjs 7.8.1 typescript 5.2.2 zone.js 0.14.2
This method works perfect if you disabled prerender
in angular.json "prerender": false
@hittten perhaps you are missing the file that the migrations create for you:
https://stackoverflow.com/a/77459798
I had the same problem but looking around I found it. I haven’t seen that in the docs though and in my view it should be created by default when you select SSR enabled
Sorry, my message was misunderstood, really the problem I show in my example is about the REQUEST and the RESPONSE . I updated my comment for better understanding:
I had to search the internet for a while to understand that I had to add the "src/express.tokens.ts" file now because it no longer comes in the @angular/ssr package, so I wrote the file manually and found another problem: The REQUEST and RESPONSE are undefined when you inject: @Optional() @Inject(RESPONSE) private response: Response
I have published a repo with the minimum to recreate the SSR problem with angular 17: > https://github.com/hittten/angularSSR17
@CarlosTorrecillas Thanks for the response, but I know I did the same thing as you.
I've been maintaining a project for a while which has more things added to server.ts than just Express tokens:
The Angular app can run fine without them, but when work needs to be done on any of those, a developer must be able to run it locally, run tests, etc...
I've spent like 3 hours praying to god, how nothing from the server.ts is executed... then found this issue :D How they could make this feature stable with this bottleneck. What's the progress?
I almost lost my last brain cell trying to understand why nothing is being executed in server.ts, this need to be documented or at least mentioned while migrating to angular 17
Is there any solution to return status code 404 in Angular 17 using @angular/ssr?
Is there any solution to return status code 404 in Angular 17 using @angular/ssr?
https://github.com/angular/angular-cli/issues/26323#issuecomment-1954498130 use it without prerender or exclude 404 page from prerender.
if you enable prerender option in @angular-devkit/build-angular:application the build procces failed because i have RESPONSE and REQUEST injections in server.ts file and angluar can not run the app for saving prerender routes, the only way that app runs successfully is to run /dist/server/server.mjs with node and injection works.
I've been closely following this discussion due to encountering the same challenge.
Upon reviewing the Angular documentation, particularly the esbuild page (https://angular.io/guide/esbuild), I noticed that it lists known issues but surprisingly omits this specific scenario. Given its critical impact on server-side rendering setups and Angular Universal implementations, including this information could be highly beneficial. It would help set proper expectations for other organizations facing similar upgrade decisions and provide much-needed clarity on the issue.
Acknowledging this challenge in the documentation and, ideally, providing a workaround or solution would greatly assist developers and companies like ours in planning our upgrade paths more effectively.
Thank you for all the hard work and dedication to improving Angular. It's genuinely appreciated, and we look forward to overcoming this hurdle with your support.
@andrewatwood Why is this a blocker for you to upgrade to Angular 17? You know that it's no requirement to use esbuild/vite in angular 17 and you can still stick to the old webpack builder?
@andrewatwood lit's no requirement to use esbuild/vite in angular 17
It's not a blocker to upgrade at all! But to ship this dev server as the default for new projects when it doesn't support an incredibly common SSR use case without any documentation about that fact, and no alternative, is very silly.
If this was an opt-in beta-level feature, it would be far less egregious. Especially since it seems primarily like an oversight with no real technical justification.
@andrewatwood lit's no requirement to use esbuild/vite in angular 17
But to ship this dev server as the default for new projects when it doesn't support an incredibly common SSR use case without any documentation about that fact, and no alternative, is very silly.
If this was an opt-in beta-level feature, it would be far less egregious. Especially since it seems primarily like an oversight with no real technical justification.
Thank you for pointing that out.
Already several months now and still nothing. Give priority to solving the problem please
This is indeed very strange. It seems that the problem is very widespread, the latest version has become unusable on SSR without any mention during the update and there is no information. The problem seems to be a major inconvenience and despite the immense gratitude for what you do, it would be nice to hear even an approximate date when you will provide us with some new information, where we stand and what are the obstacles. The RFC + open Reactivity projects showed that you can be transparent in your communication and we as a community appreciate it very much. In the case of such a popular problem, we would like to know similarly where we stand. But of course, you are in charge here.
Greetings to the Angular team and don't take this negatively. We just want to be able to use all the new things you give us :)
I'm digging internet for 12 hours and no solution, cookies coming from client not passing to api calls made by node
I have a guard that passes the cookies in a callback, it is logging undefined in the back-end even though the cookie is existing in the client. I think my issue is related to this one.
This is a known problem and we're working on resolving it. Currently, the plan is to ship it as part of the v18 release this May. If anything unexpected pops up and we're unable to deliver in this timeframe we'll follow up here.
Until v18 arrives, is there a way to inject Vite requests and read HTTP headers? In production mode, there is the possibility to inject an Express request and use it, for example, in an HTTP interceptor. However, I cannot find a way to do this in development mode with Vite. Thank you.
I did a quick proof-of-concept patch-package
patch to test how far away this really is, and it's just a handful of lines! The req
is right there: all we have to do is pass it to the render function and add it to the list of providers.
Here's a gist with my POC patch (using a plain string DI token as the actual InjectionToken
token didn't seem to resolve properly). Works like a charm, I just have to manually parse the cookies out as you can see, since my use case makes use of the cookie-parser
middleware. I'd file an actual PR, but as I mentioned before, the repo npm i --force
fails so doing actual contribution work beyond fixing typos is blocked.
NOTE: If you are actually going to use this patch, you'll need to coalesce between the actual Request
token injected value and the value injected by this plain string token wherever you consume it since they are two different tokens entirely.
@mgechev please consider scoping this specific Request
injection functionality for a v17 release sometime prior to v18 and the May release. There's obviously a lot of scope covered in these comments and this issue overall, but the above patch demonstrates that ensuring Request
gets injected in the dev server is a self-contained, low-lift piece of work.
Thanks for fielding this ticket and letting us know things are in the works!
Here's a gist with my POC patch
Though this patch seems to fix a concrete issue with cookies, I believe the root cause lies in fact that application
builder is not a drop-in replacements for @angular-devkit/build-angular:ssr-dev-server
, because the application
builder does not run the server.ts
but instead creates the in-memory one (not sure what's the right term here) to do SSR.
Not sure what's the vision of the Angular team at this point, yet the drop-in replacement is what I'd personally expect.
Summarizing all mentioned above, the following conclusion can be made.
Providing DI tokens for SSR does not work when building an application using @angular-devkit/build-angular:dev-server
. This is due to dev-server
not using server.ts
and Express itself, but using its own middleware and server.
Also, this tokens will not be available when using the prerender
option.
To solve this problem, the application needs to be built using @angular-devkit/build-angular:application
and disable the prerender
option (or exclude routes that use the tokens).
The following code can be applied:
./src/express.tokens.ts
import { InjectionToken } from '@angular/core';
import { Request, Response } from 'express';
export const REQUEST = new InjectionToken<Request>('REQUEST');
export const RESPONSE = new InjectionToken<Response>('RESPONSE');
./server.ts
...
// All regular routes use the Angular engine
server.get('*', (req, res, next) => {
const { protocol, originalUrl, baseUrl, headers } = req;
commonEngine
.render({
bootstrap,
documentFilePath: indexHtml,
url: `${protocol}://${headers.host}${originalUrl}`,
publicPath: browserDistFolder,
providers: [
{ provide: APP_BASE_HREF, useValue: baseUrl },
{ provide: REQUEST, useValue: req },
{ provide: RESPONSE, useValue: res }
],
})
.then((html) => res.send(html))
.catch((err) => next(err));
});
./src/app/app.component.ts
import {
Component,
Inject,
Optional,
PLATFORM_ID
} from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { isPlatformServer } from '@angular/common';
import { Request, Response } from 'express';
import { REQUEST, RESPONSE } from '../express.tokens';
import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet],
template: `
<h1>Welcome to {{title}}!</h1>
<router-outlet />
`,
styles: [],
})
export class AppComponent {
title = 'ssr-di';
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
@Optional() @Inject(APP_BASE_HREF) private baseUrl: string,
@Optional() @Inject(REQUEST) private request: Request,
@Optional() @Inject(RESPONSE) private response: Response
) {
if (isPlatformServer(this.platformId)) {
console.log(this.baseUrl); // baseUrl string
console.log(this.request); // Request object
console.log(this.response); // Response object
}
}
}
./src/app/not-found/not-found.component.ts
import {
Component,
Inject,
Optional,
PLATFORM_ID
} from '@angular/core';
import { isPlatformServer } from '@angular/common';
import { Response } from 'express';
import { RESPONSE } from '../../express.tokens';
@Component({
selector: 'app-not-found',
standalone: true,
imports: [],
template: `
<p>
404 not-found works!
</p>
`,
styles: ``
})
export class NotFoundComponent {
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
@Optional() @Inject(RESPONSE) private response: Response
) {
if (isPlatformServer(this.platformId)) {
this.response.status(404);
}
}
}
The most convenient way to hot reload in a development environment that I've found is to build the application using ng build --watch --configuration development
in conjunction with nodemon
.
Hope this comment helps other developers to quickly find a solution to this problem, until the Angular team resolves this issue with the v18 release.
Can you please @someApprentice explain how to serve the app to test this?
I did a quick proof-of-concept
patch-package
patch to test how far away this really is, and it's just a handful of lines! Thereq
is right there: all we have to do is pass it to the render function and add it to the list of providers.Here's a gist with my POC patch (using a plain string DI token as the actual
InjectionToken
token didn't seem to resolve properly). Works like a charm, I just have to manually parse the cookies out as you can see, since my use case makes use of thecookie-parser
middleware. I'd file an actual PR, but as I mentioned before, the reponpm i --force
fails so doing actual contribution work beyond fixing typos is blocked.NOTE: If you are actually going to use this patch, you'll need to coalesce between the actual
Request
token injected value and the value injected by this plain string token wherever you consume it since they are two different tokens entirely.@mgechev please consider scoping this specific
Request
injection functionality for a v17 release sometime prior to v18 and the May release. There's obviously a lot of scope covered in these comments and this issue overall, but the above patch demonstrates that ensuringRequest
gets injected in the dev server is a self-contained, low-lift piece of work.Thanks for fielding this ticket and letting us know things are in the works!
@andrewatwood Could you please describe here how to use this patch, or rather, how to use it? This would help many who don't have a good understanding.
Recently had to dig a bit more into vite, looks like it has the "middleware mode" which should come to the rescue 🛟
Additionally, found a vite-plugin-node
which works fine. This plugin might be useful, having the adapter
for most of the frameworks including express. Some ideas could be grasped if not to be used directly.
I
Indeed, several things about SSR need to be documented, for example since the move from @nguniversal/express-engine to @angular/ssr the express tokens were lost: https://github.com/angular/universal/blob/e798d256de5e4377b704e63d993dc56ea35df97d/modules/express-engine/tokens/injection-tokens.ts I had to search the internet for a while to understand that I had to add the "src/express.tokens.ts" file now because it no longer comes in the @angular/ssr package and that's what I did I have published a repo with the minimum to recreate the SSR problem with angular 17: https://github.com/hittten/angularSSR17
Clone & Setup:
git clone https://github.com/hittten/angularSSR17 npm install npm start
Log
Navigate to http://localhost:4200/404
ERROR TypeError: Cannot read properties of null (reading 'status') at _NotFoundPageComponent (/Workspace/hittten/angularSSR17/src/app/pages/not-found-page/not-found-page.component.ts:17:21)
Angular 16 code (working):
import {RESPONSE} from "@nguniversal/express-engine/tokens"; import {Response} from "express"; constructor( @Optional() @Inject(RESPONSE) private response: Response, @Inject(PLATFORM_ID) private platformId: object, ) { if (isPlatformServer(this.platformId)) { this.response.status(404) } else { console.error(`response status code 404`) } }
Angular 17 code (not working):
import { InjectionToken } from '@angular/core'; import { Request, Response } from 'express'; const REQUEST = new InjectionToken<Request>('REQUEST'); const RESPONSE = new InjectionToken<Response>('RESPONSE'); constructor( @Optional() @Inject(RESPONSE) private response: Response, @Inject(PLATFORM_ID) private platformId: object, ) { if (isPlatformServer(this.platformId)) { this.response.status(404) } else { console.error(`response status code 404`) } }
Info
basically I have created a project like this:
npx @angular/cli@17.0.8 new angularSSR17 --ssr --routing --scss --skip-tests cd angularSSR17 npm i -D firebase-tools@13.0.2 ng g c pages/homePage ng g c pages/aboutPage ng g c pages/notFoundPage
I also disable pre-render in angular.json:
{ "scripts": [], "server": "src/main.server.ts", "prerender": false, "ssr": { "entry": "server.ts" } }
and I have done the settings of the routes for lazy load. I have not installed @angular/fire because it is not necessary to recreate the SSR error.
And...
I also intent to provide express tokens in /server.ts: provide: REQUEST, useValue: req }, { provide: RESPONSE, useValue: res }, which is not necessary to do in angular 16, but it doesn't work either.
server.get('*', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap, documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: browserDistFolder, providers: [ { provide: APP_BASE_HREF, useValue: baseUrl }, { provide: REQUEST, useValue: req }, { provide: RESPONSE, useValue: res }, ], }) .then((html) => res.send(html)) .catch((err) => next(err)); });
Versions
Angular CLI: 17.0.8 Node: 20.10.0 Package Manager: npm 10.2.5 OS: darwin arm64 Angular: 17.0.8 ... animations, cli, common, compiler, compiler-cli, core, forms ... platform-browser, platform-browser-dynamic, platform-server ... router, ssr Package Version --------------------------------------------------------- @angular-devkit/architect 0.1700.8 @angular-devkit/build-angular 17.0.8 @angular-devkit/core 17.0.8 @angular-devkit/schematics 17.0.8 @schematics/angular 17.0.8 rxjs 7.8.1 typescript 5.2.2 zone.js 0.14.2
This method works perfect if you disabled prerender
in angular.json "prerender": false
Dude, I've been looking for hours about how to solve this specific issue. Thank you.
Hi, I have an Angular 11 (using Angular Universal) project and after struggling with hours I was able to update it to Angular 17 (with SSR). After spending extra 5-6 hours to find the solution I found this open issue. In fact I am facing with the same issue that @mkurcius wrote. Am I understand correctly that currently there is no way to make fullstack Angular v17 apps using the generated server.ts file?
No, it's not possible for now. https://github.com/angular/angular-cli/issues/26323#issuecomment-1971390348
I need host from headers to properly render og meta tags, and spend so much time to make it work, but providers not providing...
This is a known problem and we're working on resolving it. Currently, the plan is to ship it as part of the v18 release this May. If anything unexpected pops up and we're unable to deliver in this timeframe we'll follow up here.
Hey, @mgechev. Is there still a chance for SSR fix in version 18?
I need host from headers to properly render og meta tags, and spend so much time to make it work, but providers not providing...
If you refer usage of meta tags of Document it's possible with Resolver and inject Meta
See this https://medium.com/@shravanvishwakarma5/meta-tags-in-angular-c483c3e6f0d4
Only use in resolvers and work correctly , in my case usage a variant more overhead because i need show imagen a pre prender pages
I am not the best in Angular. I just wanted to work with
server.ts
locally in Angular 17. So I came up with the following:
- Open 2 terminals.
- On the first terminal run
ng build --watch --configuration development
. Your code will re-build every time you save the code.- On the second terminal run
node dist/my-project/server/server.mjs
.- Reload page after save. Sometimes build is cached, so to fix this, check Disable cache in the Network tab in browser's DEV tools.
This is simple workaround. If someone can show better approach, please reply to this comment. Thanks!
That way works, but losse the hot reload and source maping for all application, anyone have a better workarround for while?
I try improve with nodemon and --enable-source-maps but nothing change, only auto restart the server when files changes, but need refresh the browser.
I'm ussing the server.ts expresse to run API Proxy and Auth routes (Back For Front)
For SSR development accessing to server request and response objects is a MUST TO HAVE feature in both development and production envs
This is becoming scary as I didn't see any changes about this issue in development versions of v18
No alternative and clean solution for this until now!
The solutions introduced here are absolutely dirty!!
If this remains without a proper solution (fix or alternative) I'll probably reconsider about my entire frontend stack!!
Hello, when can this problem be expected to be solved?
@Fronikuniu I hope tomorrow with v18 release.
@Fronikuniu I hope tomorrow with v18 release.
Today in my country release Angular 18 but i dont see relative change to issue , I haven't tried it yet in my project
For SSR development accessing to server request and response objects is a MUST TO HAVE feature in both development and production envs This is becoming scary as I didn't see any changes about this issue in development versions of v18 No alternative and clean solution for this until now! The solutions introduced here are absolutely dirty!! If this remains without a proper solution (fix or alternative) I'll probably reconsider about my entire frontend stack!!
sadly i totally agree. i guess no one can start a project with absolutely dirty solutions hoping for fixs..
This is a known problem and we're working on resolving it. Currently, the plan is to ship it as part of the v18 release this May. If anything unexpected pops up and we're unable to deliver in this timeframe we'll follow up here.
and as of version 18 nothing changed .. nothing is mentioned in the CHANGELOG.md nor in the Angular v18 is now available! blog post.
i don't want be that guy but i guess we waiting for the follow up ..
For SSR development accessing to server request and response objects is a MUST TO HAVE feature in both development and production envs This is becoming scary as I didn't see any changes about this issue in development versions of v18 No alternative and clean solution for this until now! The solutions introduced here are absolutely dirty!! If this remains without a proper solution (fix or alternative) I'll probably reconsider about my entire frontend stack!!
sadly i totally agree. i guess no one can start a project with absolutely dirty solutions hoping for fixs..
This is a known problem and we're working on resolving it. Currently, the plan is to ship it as part of the v18 release this May. If anything unexpected pops up and we're unable to deliver in this timeframe we'll follow up here.
and as of version 18 nothing changed .. nothing is mentioned in the CHANGELOG.md nor in the Angular v18 is now available! blog post.
i don't want be that guy but i guess we waiting for the follow up ..
I hope it is fixed in a minor fix or something soon, which I also hope to update my monorepo project in Nx
NX upgrades lag behind Angular, usually taking a few days to catch up. we all aboard the wait train
I just tried an experimental upgrade to v18 to see if this issue is resolved and it's clear that it has not, though given the lack of any official communication on this issue leading up to release, this outcome is not surprising.
For my team's use case, we didn't have a good way to bring SSR directly into our dev server prior to v17 anyway (given the complexity of our application), so it's not dire that we can't run a valid SSR configuration right now, but clearly other users did have this capability in previous Angular versions with Universal. It's highly unfortunate that the Angular team could not provide even a cursory update about how or whether this issue would be addressed in Angular 18, despite promising to do so (https://github.com/angular/angular-cli/issues/26323#issuecomment-1971390348). The upgrade marketing was that we would not need Angular Universal at all, because it was all brought into the core framework. As part of that, Angular Universal was never updated to work with v17, so folks who had a solid workflow in the old system either have to abandon SSR in their development workflow or stay behind on previous versions- it looks like that will continue with Angular 18.
The promise of a straightforward, fast dev server native solution for Angular SSR which runs the application's entire codebase is extremely appealing for the community, regardless of whether an SSR dev experience worked prior. Not providing updates on resolution here raises eyebrows.
I'm not mad about v18 not shipping a solution, I'm just incredibly disappointed in the lack of communication. I'm sure I'm not the only one hoping that Angular can provide a suitable explanation for failing to address this in v18. It's highly questionable that the v17 Application Builder was shipped at all without considering what would happen if the core server entrypoint was not executed. I still struggle to understand what the Angular team expected "ssr": true
to be useful for with the state it was shipped in.
You might find the following workaround very useful, until Angular fixes this issue - the article by @pawelfras: 🙌
✅ run SSR dev server
✅ server.ts
included
✅ fast application
builder
✅ Angular 17+
I can't do anything useful with SSR without accessing the request in my app 😡.
Which @angular/* package(s) are the source of the bug?
Don't known / other
Is this a regression?
Yes
Description
Prior to upgrading to v17 our application passed express' req/res as REQUEST/RESPONSE DI Tokens through the render function of the engine in server.ts. Since upgrading to v17 from v16 these DI Token values are always null.
This can be seen in the minimal reproduction where all three of APP_BASE_HREF / REQUEST / RESPONSE are null in the console output while running 'ng serve'.
If using @angular-devkit/build-angular:browser instead of @angular-devkit/build-angular:application this problem does not occur. I assume there is a different way to provide dependencies from server.ts now but I have not been able to find any updated documentation on it.
Please provide a link to a minimal reproduction of the bug
https://github.com/Ozzcer/angular-ssr-di-issue
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run
ng version
)Anything else?
No response