mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
added CSR fallback and optionally disable SSR
This commit is contained in:
@@ -15,11 +15,19 @@ module.exports = {
|
|||||||
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
|
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
|
||||||
nameSpace: '/dspace-spring-rest/api'
|
nameSpace: '/dspace-spring-rest/api'
|
||||||
},
|
},
|
||||||
|
// Caching settings
|
||||||
cache: {
|
cache: {
|
||||||
// NOTE: how long should objects be cached for by default
|
// NOTE: how long should objects be cached for by default
|
||||||
msToLive: 15 * 60 * 1000, // 15 minute
|
msToLive: 15 * 60 * 1000, // 15 minute
|
||||||
control: 'max-age=60' // revalidate browser
|
control: 'max-age=60' // revalidate browser
|
||||||
},
|
},
|
||||||
|
// Angular Universal settings
|
||||||
|
universal: {
|
||||||
|
preboot: true,
|
||||||
|
async: true,
|
||||||
|
time: false
|
||||||
|
},
|
||||||
|
// Log directory
|
||||||
logDirectory: '.',
|
logDirectory: '.',
|
||||||
// NOTE: rehydrate or replay
|
// NOTE: rehydrate or replay
|
||||||
// rehydrate will transfer prerender state to browser state, actions do not need to replay
|
// rehydrate will transfer prerender state to browser state, actions do not need to replay
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"watch": [
|
"watch": [
|
||||||
"dist",
|
"dist",
|
||||||
|
"config",
|
||||||
"src/index.html"
|
"src/index.html"
|
||||||
],
|
],
|
||||||
"ext": "js ts json html"
|
"ext": "js ts json html"
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
import { ServerConfig } from './server-config.interface';
|
import { ServerConfig } from './server-config.interface';
|
||||||
import { CacheConfig } from './cache-config.interface';
|
import { CacheConfig } from './cache-config.interface';
|
||||||
|
import { UniversalConfig } from './universal-config.interface';
|
||||||
|
|
||||||
export interface GlobalConfig {
|
export interface GlobalConfig {
|
||||||
ui: ServerConfig;
|
ui: ServerConfig;
|
||||||
rest: ServerConfig;
|
rest: ServerConfig;
|
||||||
prerenderStrategy: string;
|
|
||||||
production: boolean;
|
production: boolean;
|
||||||
cache: CacheConfig;
|
cache: CacheConfig;
|
||||||
|
universal: UniversalConfig;
|
||||||
logDirectory: string;
|
logDirectory: string;
|
||||||
|
prerenderStrategy: string;
|
||||||
debug: boolean;
|
debug: boolean;
|
||||||
}
|
}
|
||||||
|
5
src/config/universal-config.interface.ts
Normal file
5
src/config/universal-config.interface.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export interface UniversalConfig {
|
||||||
|
preboot: boolean,
|
||||||
|
async: boolean,
|
||||||
|
time: boolean
|
||||||
|
}
|
19
src/index.csr.html
Normal file
19
src/index.csr.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<base href="/">
|
||||||
|
<title>DSpace</title>
|
||||||
|
<meta name="viewport" content="width=device-width,minimum-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="assets/images/favicon.ico" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ds-app></ds-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!-- this is needed for CSR fallback -->
|
||||||
|
<script async src="/client.js"></script>
|
||||||
|
|
||||||
|
</html>
|
@@ -13,4 +13,6 @@
|
|||||||
<ds-app></ds-app>
|
<ds-app></ds-app>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
<!-- do not include client bundle, it is injected with Zone already loaded -->
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@@ -56,7 +56,7 @@ app.set('view engine', 'html');
|
|||||||
app.set('views', 'src');
|
app.set('views', 'src');
|
||||||
|
|
||||||
function cacheControl(req, res, next) {
|
function cacheControl(req, res, next) {
|
||||||
// instruct browser to revalidate in 60 seconds
|
// instruct browser to revalidate
|
||||||
res.header('Cache-Control', ENV_CONFIG.cache.control || 'max-age=60');
|
res.header('Cache-Control', ENV_CONFIG.cache.control || 'max-age=60');
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
@@ -67,18 +67,34 @@ app.use('/', cacheControl, express.static('dist', { index: false }));
|
|||||||
// app.get('/data.json', serverApi);
|
// app.get('/data.json', serverApi);
|
||||||
// app.use('/api', createMockApi());
|
// app.use('/api', createMockApi());
|
||||||
|
|
||||||
|
function ngApp(req, res) {
|
||||||
|
|
||||||
|
function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
|
||||||
|
console.warn('Error in SSR, serving for direct CSR');
|
||||||
|
res.sendFile('index.csr.html', { root: './src' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ENV_CONFIG.universal.preboot) {
|
||||||
|
Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
|
||||||
|
res.render('../dist/index', {
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
preboot: ENV_CONFIG.universal.preboot,
|
||||||
|
async: ENV_CONFIG.universal.async,
|
||||||
|
time: ENV_CONFIG.universal.time,
|
||||||
|
baseUrl: ENV_CONFIG.ui.nameSpace,
|
||||||
|
originUrl: ENV_CONFIG.ui.baseUrl,
|
||||||
|
requestUrl: req.originalUrl
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Universal preboot off, service for direct CSD');
|
||||||
|
res.sendFile('index.csr.html', { root: './src' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ROUTES.forEach((route: string) => {
|
ROUTES.forEach((route: string) => {
|
||||||
app.get(route, (req, res) => {
|
app.get(route, ngApp);
|
||||||
res.cookie('ui_origin', ENV_CONFIG.ui.baseUrl, {
|
|
||||||
maxAge: 1000 * 60 * 15,
|
|
||||||
httpOnly: true,
|
|
||||||
signed: false
|
|
||||||
});
|
|
||||||
res.render('../dist/index', {
|
|
||||||
req: req,
|
|
||||||
res: res
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function serverStarted() {
|
function serverStarted() {
|
||||||
|
@@ -44,7 +44,7 @@ app.set('view engine', 'html');
|
|||||||
app.set('views', 'src');
|
app.set('views', 'src');
|
||||||
|
|
||||||
function cacheControl(req, res, next) {
|
function cacheControl(req, res, next) {
|
||||||
// instruct browser to revalidate in 60 seconds
|
// instruct browser to revalidate
|
||||||
res.header('Cache-Control', ENV_CONFIG.cache.control || 'max-age=60');
|
res.header('Cache-Control', ENV_CONFIG.cache.control || 'max-age=60');
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
@@ -55,18 +55,34 @@ app.use('/', cacheControl, express.static('dist', { index: false }));
|
|||||||
// app.get('/data.json', serverApi);
|
// app.get('/data.json', serverApi);
|
||||||
// app.use('/api', createMockApi());
|
// app.use('/api', createMockApi());
|
||||||
|
|
||||||
|
function ngApp(req, res) {
|
||||||
|
|
||||||
|
function onHandleError(parentZoneDelegate, currentZone, targetZone, error) {
|
||||||
|
console.warn('Error in SSR, serving for direct CSR');
|
||||||
|
res.sendFile('index.csr.html', { root: './src' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ENV_CONFIG.universal.preboot) {
|
||||||
|
Zone.current.fork({ name: 'CSR fallback', onHandleError }).run(() => {
|
||||||
|
res.render('../dist/index', {
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
preboot: ENV_CONFIG.universal.preboot,
|
||||||
|
async: ENV_CONFIG.universal.async,
|
||||||
|
time: ENV_CONFIG.universal.time,
|
||||||
|
baseUrl: ENV_CONFIG.ui.nameSpace,
|
||||||
|
originUrl: ENV_CONFIG.ui.baseUrl,
|
||||||
|
requestUrl: req.originalUrl
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('Universal preboot off, service for direct CSD');
|
||||||
|
res.sendFile('index.csr.html', { root: './src' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ROUTES.forEach((route: string) => {
|
ROUTES.forEach((route: string) => {
|
||||||
app.get(route, (req, res) => {
|
app.get(route, ngApp);
|
||||||
res.cookie('ui_origin', ENV_CONFIG.ui.baseUrl, {
|
|
||||||
maxAge: 1000 * 60 * 15,
|
|
||||||
httpOnly: true,
|
|
||||||
signed: false
|
|
||||||
});
|
|
||||||
res.render('../dist/index', {
|
|
||||||
req: req,
|
|
||||||
res: res
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function serverStarted() {
|
function serverStarted() {
|
||||||
|
@@ -27,7 +27,7 @@ export class BrowserTransferState extends TransferState {
|
|||||||
if (this.config.prerenderStrategy === 'replay') {
|
if (this.config.prerenderStrategy === 'replay') {
|
||||||
if (cache.actions !== undefined) {
|
if (cache.actions !== undefined) {
|
||||||
if (this.config.debug) {
|
if (this.config.debug) {
|
||||||
console.info('Replay:', cache.actions);
|
console.info('Replay:', (cache.actions !== undefined && cache.actions !== null) ? cache.actions : []);
|
||||||
}
|
}
|
||||||
this.store.dispatch(new StoreAction(StoreActionTypes.REPLAY, cache.actions));
|
this.store.dispatch(new StoreAction(StoreActionTypes.REPLAY, cache.actions));
|
||||||
} else {
|
} else {
|
||||||
@@ -35,7 +35,7 @@ export class BrowserTransferState extends TransferState {
|
|||||||
}
|
}
|
||||||
} else if (this.config.prerenderStrategy === 'rehydrate') {
|
} else if (this.config.prerenderStrategy === 'rehydrate') {
|
||||||
if (this.config.debug) {
|
if (this.config.debug) {
|
||||||
console.info('Rehydrate:', cache.state);
|
console.info('Rehydrate:', (cache.state !== undefined && cache.state !== null) ? cache.state : []);
|
||||||
}
|
}
|
||||||
this.store.dispatch(new StoreAction(StoreActionTypes.REHYDRATE, cache.state));
|
this.store.dispatch(new StoreAction(StoreActionTypes.REHYDRATE, cache.state));
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user