diff --git a/src/server/template-renderer/index.js b/src/server/template-renderer/index.js
index c8927b2de2c..5cfdef53d49 100644
--- a/src/server/template-renderer/index.js
+++ b/src/server/template-renderer/index.js
@@ -14,6 +14,9 @@ type TemplateRendererOptions = {
template?: string | (content: string, context: any) => string;
inject?: boolean;
clientManifest?: ClientManifest;
+ getPrefetchLinkAttrs?: (ref: Resource) => Resource;
+ getPreloadLinkAttrs?: (ref: Resource) => Resource;
+ getScriptAttrs?: (ref: Resource) => Resource;
shouldPreload?: (file: string, type: string) => boolean;
shouldPrefetch?: (file: string, type: string) => boolean;
serializer?: Function;
@@ -37,6 +40,7 @@ type Resource = {
extension: string;
fileWithoutQuery: string;
asType: string;
+ attrs?: string;
};
export default class TemplateRenderer {
@@ -55,7 +59,7 @@ export default class TemplateRenderer {
this.inject = options.inject !== false
// if no template option is provided, the renderer is created
// as a utility object for rendering assets like preload links and scripts.
-
+
const { template } = options
this.parsedTemplate = template
? typeof template === 'string'
@@ -156,10 +160,13 @@ export default class TemplateRenderer {
renderPreloadLinks (context: Object): string {
const files = this.getPreloadFiles(context)
- const shouldPreload = this.options.shouldPreload
if (files.length) {
- return files.map(({ file, extension, fileWithoutQuery, asType }) => {
- let extra = ''
+ const { getPreloadLinkAttrs, shouldPreload } = this.options
+ return files.map(ref => {
+ if(typeof getPreloadLinkAttrs === 'function') {
+ ref = getPreloadLinkAttrs(ref)
+ }
+ const { file, extension, fileWithoutQuery, asType, attrs } = ref
// by default, we only preload scripts or css
if (!shouldPreload && asType !== 'script' && asType !== 'style') {
return ''
@@ -168,6 +175,9 @@ export default class TemplateRenderer {
if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) {
return ''
}
+
+ let extra = attrs || ''
+
if (asType === 'font') {
extra = ` type="font/${extension}" crossorigin`
}
@@ -185,20 +195,25 @@ export default class TemplateRenderer {
}
renderPrefetchLinks (context: Object): string {
- const shouldPrefetch = this.options.shouldPrefetch
+ const { getPrefetchLinkAttrs, shouldPrefetch } = this.options
if (this.prefetchFiles) {
const usedAsyncFiles = this.getUsedAsyncFiles(context)
const alreadyRendered = file => {
return usedAsyncFiles && usedAsyncFiles.some(f => f.file === file)
}
- return this.prefetchFiles.map(({ file, fileWithoutQuery, asType }) => {
+ return this.prefetchFiles.map(ref => {
+ if(typeof getPrefetchLinkAttrs === 'function') {
+ ref = getPrefetchLinkAttrs(ref)
+ }
+ const { file, fileWithoutQuery, asType } = ref
if (shouldPrefetch && !shouldPrefetch(fileWithoutQuery, asType)) {
return ''
}
if (alreadyRendered(file)) {
return ''
}
- return ``
+ const { attrs='rel="prefetch"' } = ref
+ return ``
}).join('')
} else {
return ''
@@ -225,8 +240,13 @@ export default class TemplateRenderer {
const initial = this.preloadFiles.filter(({ file }) => isJS(file))
const async = (this.getUsedAsyncFiles(context) || []).filter(({ file }) => isJS(file))
const needed = [initial[0]].concat(async, initial.slice(1))
- return needed.map(({ file }) => {
- return ``
+ const { getScriptAttrs } = this.options
+ return needed.map((ref) => {
+ if(typeof getScriptAttrs === 'function') {
+ ref = getScriptAttrs(ref)
+ }
+ const { file, attrs = 'defer' } = ref
+ return ``
}).join('')
} else {
return ''