diff --git a/config/config.example.yml b/config/config.example.yml index d5e7dfe5016..a9de709deaa 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -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(/.*)?$", + 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. diff --git a/server.ts b/server.ts index 52b2823d49c..cf21eda6af9 100644 --- a/server.ts +++ b/server.ts @@ -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 @@ -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 { @@ -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 */ diff --git a/src/config/ssr-config.interface.ts b/src/config/ssr-config.interface.ts index 2ce626b47b8..16bb3f54d66 100644 --- a/src/config/ssr-config.interface.ts +++ b/src/config/ssr-config.interface.ts @@ -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 @@ -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; + excludePathPatterns: SsrExcludePatterns[]; /** * Whether to enable rendering of search component on SSR diff --git a/src/environments/environment.production.ts b/src/environments/environment.production.ts index 9bd663922c8..21cc8a25ea3 100644 --- a/src/environments/environment.production.ts +++ b/src/environments/environment.production.ts @@ -10,7 +10,25 @@ export const environment: Partial = { 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, }, diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index b6348f949d5..ee59d09d734 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -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, }, diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 39ab31de03e..2b6b6d9fd80 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -15,7 +15,25 @@ export const environment: Partial = { 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, },