Merge pull request #4325 from DSpace/backport-4227-to-dspace-8_x

[Port dspace-8_x] Remove `ssr.paths` configuration and replace with `ssr.excludePathPatterns` which excludes specific paths from SSR
This commit is contained in:
Tim Donohue
2025-05-12 15:58:45 -05:00
committed by GitHub
6 changed files with 99 additions and 10 deletions

View File

@@ -23,10 +23,24 @@ ssr:
# Determining which styles are critical is a relatively expensive operation; this option is # 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. # disabled (false) by default to boost server performance at the expense of loading smoothness.
inlineCriticalCss: false inlineCriticalCss: false
# Path prefixes to enable SSR for. By default these are limited to paths of primary DSpace objects. # Patterns to be run as regexes against the path of the page to check if SSR is allowed.
# NOTE: The "/handle/" path ensures Handle redirects work via SSR. The "/reload/" path ensures # If the path match any of the regexes it will be served directly in CSR.
# hard refreshes (e.g. after login) trigger SSR while fully reloading the page. # By default, excludes community and collection browse, global browse, global search, community list, statistics and various administrative tools.
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: "^/admin/"
- pattern: "^/processes/?"
- pattern: "^/notifications/"
- pattern: "^/statistics/?"
- pattern: "^/access-control/"
- pattern: "^/health$"
# Whether to enable rendering of Search component on SSR. # 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 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. # If set to false the component will not be included in the HTML returned from the server side rendering.

View File

@@ -58,6 +58,7 @@ import {
REQUEST, REQUEST,
RESPONSE, RESPONSE,
} from './src/express.tokens'; } from './src/express.tokens';
import { SsrExcludePatterns } from "./src/config/ssr-config.interface";
/* /*
* Set path for the browser application's dist folder * Set path for the browser application's dist folder
@@ -221,7 +222,7 @@ export function app() {
* The callback function to serve server side angular * The callback function to serve server side angular
*/ */
function ngApp(req, res, next) { 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) // Render the page to user via SSR (server side rendering)
serverSideRender(req, res, next); serverSideRender(req, res, next);
} else { } else {
@@ -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 * The callback function to serve health check requests
*/ */

View File

@@ -1,5 +1,10 @@
import { Config } from './config.interface'; import { Config } from './config.interface';
export interface SsrExcludePatterns {
pattern: string | RegExp;
flag?: string;
}
export interface SSRConfig extends Config { export interface SSRConfig extends Config {
/** /**
* A boolean flag indicating whether the SSR configuration is enabled * A boolean flag indicating whether the SSR configuration is enabled
@@ -39,9 +44,9 @@ export interface SSRConfig extends Config {
replaceRestUrl: boolean; 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 * Whether to enable rendering of search component on SSR

View File

@@ -10,7 +10,25 @@ export const environment: Partial<BuildConfig> = {
inlineCriticalCss: false, inlineCriticalCss: false,
transferState: true, transferState: true,
replaceRestUrl: 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, enableSearchComponent: false,
enableBrowseComponent: false, enableBrowseComponent: false,
}, },

View File

@@ -14,7 +14,25 @@ export const environment: BuildConfig = {
inlineCriticalCss: false, inlineCriticalCss: false,
transferState: true, transferState: true,
replaceRestUrl: false, 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, enableSearchComponent: false,
enableBrowseComponent: false, enableBrowseComponent: false,
}, },

View File

@@ -15,7 +15,25 @@ export const environment: Partial<BuildConfig> = {
inlineCriticalCss: false, inlineCriticalCss: false,
transferState: true, transferState: true,
replaceRestUrl: false, 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, enableSearchComponent: false,
enableBrowseComponent: false, enableBrowseComponent: false,
}, },