-
Notifications
You must be signed in to change notification settings - Fork 439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a setting to use a different REST url during SSR execution #3358
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything works as expected, but still "leaks" the SSR URL and does double work since the transfer state is ignored
map(() => true), | ||
), | ||
); | ||
// The app state can be transferred only when SSR and CSR are using the same base url for the REST API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A separate REST URL could be a performance benefit during SSR, but if we discard all cached requests we'll always do double work and CSR performance will suffer.
Could we consider just running a search/replace on the transfer state to replace the SSR URL with the CSR URL?
- This shouldn't be too heavy of an operation so I think the net impact on performance could still be positive
- I did a very quick check and replacing all URLs right after the full HTML has been generated takes at most 0.25% of the total time needed for SSR
- Only tested for
/home
, not authenticated - SSR took ~400ms, HTML search replace took between 0 and 1ms
- Only tested for
Otherwise we should at least exclude the transfer state entirely; right now it's sent but never read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your suggestion, but I believe implementing a search/replace operation for URLs might not be a good idea due to performance concerns. Even though the initial tests show a minimal impact, this might not be the case for all routes or under different conditions and it could become a bottleneck.
Moreover adding an extra step in the Server-side rendering process can increase the overall latency, negatively affecting the user experience, particularly for pages with larger amount of request.
Honestly I don't see a real issue to fetch again the request during the CSR.
I'll try to exclude the transfer state entirely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly I don't see a real issue to fetch again the request during the CSR
My main concern is that it has a significant impact on perceived performance, especially on slower connections.
This counteracts our push towards decreasing the amount of REST requests we send ~ #3110 (comment).
I've made a quick branch where you can toggle both things: ybnd/dspace-angular → task/main/DURACOM-288
ui.transferState
→ whether NGRX state is transferred from SSR to CSRreplaceRestUrl
→ whether the SSR URL is replaced after SSR is done
As far as I can tell, a simple RegEx to replace SSR URLs scales a lot better than DSpace itself
- A
/search
page with 1000 results (!) takes ~50000ms to build with SSR on my machine - Replacing all URLs (~16000) takes ~20ms
On the other hand, for a /search
page with 100 results, Lighthouse reports about double the blocking time if we don't transfer state on CSR.
@@ -100,6 +101,14 @@ export class ServerInitService extends InitService { | |||
} | |||
|
|||
private saveAppConfigForCSR(): void { | |||
this.transferState.set<AppConfig>(APP_CONFIG_STATE, environment as AppConfig); | |||
if (isNotEmpty(environment.rest.ssrBaseUrl) && environment.rest.baseUrl !== environment.rest.ssrBaseUrl) { | |||
// Avoid to transfer ssrBaseUrl in order to prevent security issues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree about the potential security concern, good idea.
The state transfer JSON will still list the SSR URL. It's a bit more "hidden" but not secure either.
Hi @atarix83, |
# Conflicts: # src/app/thumbnail/thumbnail.component.spec.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @atarix83 ! I gave this a code review today, and have some minor requests for improvement. I haven't had a chance to fully test this yet, but I plan to do so next week.
let redirectUrl = url; | ||
// If redirect url contains SSR base url then replace with public base url | ||
if (isNotEmpty(this.appConfig.rest.ssrBaseUrl) && this.appConfig.rest.baseUrl !== this.appConfig.rest.ssrBaseUrl) { | ||
redirectUrl = url.replace(this.appConfig.rest.ssrBaseUrl, this.appConfig.rest.baseUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a basic test to server-hard-redirect.service.spec.ts
to prove this replacement is working properly? This code appears to be missing specs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -6,4 +6,6 @@ export class ServerConfig implements Config { | |||
public port: number; | |||
public nameSpace: string; | |||
public baseUrl?: string; | |||
public ssrBaseUrl?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add this new ssrBaseUrl
setting to our config.example.yml
. Currently, it's undocumented and "hidden".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -6,4 +6,6 @@ export class ServerConfig implements Config { | |||
public port: number; | |||
public nameSpace: string; | |||
public baseUrl?: string; | |||
public ssrBaseUrl?: string; | |||
public hasSsrBaseUrl?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add a comment here to describe how/where this boolean value is set? This doesn't appear to be something we want people to specify in their config.yml
, so it would be good to document that this is set automatically based on the value of ssrBaseUrl
in your config.
…ting enter in another input form (onsubmit)
…esetting-on-enter_contribute-7.6' # Conflicts: # src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html
…ting the enter key in another input field
I've improved my implementation trying to address your feedback. Here the main changes:
|
References
Add references/links to any related issues or PRs. These may include:
Description
This pull request provide the possibility to use a different DSpace REST url during the SSR
Instructions for Reviewers
List of changes in this PR:
ssrBaseUrl
where to specify a different DSpace REST url to use during SSRssrBaseUrl
property. If this URL was not publicly accessible, it would result in an error. By rendering the thumbnail only in the browser, we avoid this problem.ServerHardRedirectService
. In case the url to redirect contains thessrBaseUrl
it's reinstated with the public base url. This is necessary otherwise download bitstream page doesn't work.Include guidance for how to test or review your PR.
Unfortunately it is difficult to test this PR. The best would be to deploy it in a production like environment and configure the internal base url property.
This might be done on both Angular and REST side, like in the example below where public base url is
https://dspace-rest.org/server
and internal base url ishttp://localhost:8080/server
.ssrBaseUrl
property, e.g :dspace.server.ssr.url
property, e.g. :In order to test it locally you could add an alias hostname for localhost ip to be used as public url
Checklist
main
branch of code (unless it is a backport or is fixing an issue specific to an older branch).npm run lint
npm run check-circ-deps
)package.json
), I've made sure their licenses align with the DSpace BSD License based on the Licensing of Contributions documentation.