Skip to content

Remove ssr.paths configuration and replace with ssr.excludePathPatterns which excludes specific paths from SSR #4227

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

Merged
merged 3 commits into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,24 @@ ssr:
# Determining which styles are critical is a relatively expensive operation; this option is
# disabled (false) by default to boost server performance at the expense of loading smoothness.
inlineCriticalCss: false
# Path prefixes to enable SSR for. By default these are limited to paths of primary DSpace objects.
# NOTE: The "/handle/" path ensures Handle redirects work via SSR. The "/reload/" path ensures
# hard refreshes (e.g. after login) trigger SSR while fully reloading the page.
paths: [ '/home', '/items/', '/entities/', '/collections/', '/communities/', '/bitstream/', '/bitstreams/', '/handle/', '/reload/' ]
# Patterns to be run as regexes against the path of the page to check if SSR is allowed.
# If the path match any of the regexes it will be served directly in CSR.
# By default, excludes community and collection browse, global browse, global search, community list, statistics and various administrative tools.
excludePathPatterns:
- pattern: "^/communities/[a-f0-9-]{36}/browse(/.*)?$",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was testing this functionality and it wasn't reading the configuration correctly. I had to remove the trailing comma from this line — I guess it's a copy & paste error and it shouldn't be there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@toniprieto : Yes, you are correct. That appears to be a copy & paste error. The comma should not be there. Would you have time to create a small PR to fix this? If not, I can do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll do it now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created a PR at #4364 Will quickly fix in 9.0 prior to release

flag: "i"
- pattern: "^/collections/[a-f0-9-]{36}/browse(/.*)?$"
flag: "i"
- pattern: "^/browse/"
- pattern: "^/search$"
- pattern: "^/community-list$"
- pattern: "^/admin/"
- pattern: "^/processes/?"
- pattern: "^/notifications/"
- pattern: "^/statistics/?"
- pattern: "^/access-control/"
- pattern: "^/health$"

# Whether to enable rendering of Search component on SSR.
# If set to true the component will be included in the HTML returned from the server side rendering.
# If set to false the component will not be included in the HTML returned from the server side rendering.
Expand Down
18 changes: 17 additions & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
REQUEST,
RESPONSE,
} from './src/express.tokens';
import { SsrExcludePatterns } from "./src/config/ssr-config.interface";

/*
* Set path for the browser application's dist folder
Expand Down Expand Up @@ -221,7 +222,7 @@ export function app() {
* The callback function to serve server side angular
*/
function ngApp(req, res, next) {
if (environment.ssr.enabled && req.method === 'GET' && (req.path === '/' || environment.ssr.paths.some(pathPrefix => req.path.startsWith(pathPrefix)))) {
if (environment.ssr.enabled && req.method === 'GET' && (req.path === '/' || !isExcludedFromSsr(req.path, environment.ssr.excludePathPatterns))) {
// Render the page to user via SSR (server side rendering)
serverSideRender(req, res, next);
} else {
Expand Down Expand Up @@ -627,6 +628,21 @@ function start() {
}
}

/**
* Check if SSR should be skipped for path
*
* @param path
* @param excludePathPattern
*/
function isExcludedFromSsr(path: string, excludePathPattern: SsrExcludePatterns[]): boolean {
const patterns = excludePathPattern.map(p =>
new RegExp(p.pattern, p.flag || '')
);
return patterns.some((regex) => {
return regex.test(path)
});
}

/*
* The callback function to serve health check requests
*/
Expand Down
9 changes: 7 additions & 2 deletions src/config/ssr-config.interface.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Config } from './config.interface';

export interface SsrExcludePatterns {
pattern: string | RegExp;
flag?: string;
}

export interface SSRConfig extends Config {
/**
* A boolean flag indicating whether the SSR configuration is enabled
Expand Down Expand Up @@ -39,9 +44,9 @@ export interface SSRConfig extends Config {
replaceRestUrl: boolean;

/**
* Paths to enable SSR for. Defaults to the home page and paths in the sitemap.
* Patterns to be used as regexes to match url's path and check if SSR is disabled for it.
*/
paths: Array<string>;
excludePathPatterns: SsrExcludePatterns[];

/**
* Whether to enable rendering of search component on SSR
Expand Down
20 changes: 19 additions & 1 deletion src/environments/environment.production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,25 @@ export const environment: Partial<BuildConfig> = {
inlineCriticalCss: false,
transferState: true,
replaceRestUrl: true,
paths: [ '/home', '/items/', '/entities/', '/collections/', '/communities/', '/bitstream/', '/bitstreams/', '/handle/', '/reload/' ],
excludePathPatterns: [
{
pattern: '^/communities/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{
pattern: '^/collections/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{ pattern: '^/browse/' },
{ pattern: '^/search' },
{ pattern: '^/community-list$' },
{ pattern: '^/statistics/?' },
{ pattern: '^/admin/' },
{ pattern: '^/processes/?' },
{ pattern: '^/notifications/' },
{ pattern: '^/access-control/' },
{ pattern: '^/health$' },
],
enableSearchComponent: false,
enableBrowseComponent: false,
},
Expand Down
20 changes: 19 additions & 1 deletion src/environments/environment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,25 @@ export const environment: BuildConfig = {
inlineCriticalCss: false,
transferState: true,
replaceRestUrl: false,
paths: [ '/home', '/items/', '/entities/', '/collections/', '/communities/', '/bitstream/', '/bitstreams/', '/handle/', '/reload/' ],
excludePathPatterns: [
{
pattern: '^/communities/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{
pattern: '^/collections/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{ pattern: '^/browse/' },
{ pattern: '^/search' },
{ pattern: '^/community-list$' },
{ pattern: '^/statistics/?' },
{ pattern: '^/admin/' },
{ pattern: '^/processes/?' },
{ pattern: '^/notifications/' },
{ pattern: '^/access-control/' },
{ pattern: '^/health$' },
],
enableSearchComponent: false,
enableBrowseComponent: false,
},
Expand Down
20 changes: 19 additions & 1 deletion src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,25 @@ export const environment: Partial<BuildConfig> = {
inlineCriticalCss: false,
transferState: true,
replaceRestUrl: false,
paths: [ '/home', '/items/', '/entities/', '/collections/', '/communities/', '/bitstream/', '/bitstreams/', '/handle/', '/reload/' ],
excludePathPatterns: [
{
pattern: '^/communities/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{
pattern: '^/collections/[a-f0-9-]{36}/browse(/.*)?$',
flag: 'i',
},
{ pattern: '^/browse/' },
{ pattern: '^/search' },
{ pattern: '^/community-list$' },
{ pattern: '^/statistics/?' },
{ pattern: '^/admin/' },
{ pattern: '^/processes/?' },
{ pattern: '^/notifications/' },
{ pattern: '^/access-control/' },
{ pattern: '^/health$' },
],
enableSearchComponent: false,
enableBrowseComponent: false,
},
Expand Down
Loading