From 6e45bfec070bf72a07c69369a301b5b80b58e74e Mon Sep 17 00:00:00 2001 From: Clark Du Date: Sat, 8 Feb 2020 22:17:28 +0000 Subject: [PATCH 1/2] feat(ssr): support coustom attributes in render scripts --- src/server/template-renderer/index.js | 37 ++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/server/template-renderer/index.js b/src/server/template-renderer/index.js index c8927b2de2c..d8106070769 100644 --- a/src/server/template-renderer/index.js +++ b/src/server/template-renderer/index.js @@ -55,7 +55,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 +156,14 @@ 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 + const hasAttrsFn = typeof getPreloadLinkAttrs === 'function' + return files.map(ref => { + if(hasAttrsFn) { + 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 +172,9 @@ export default class TemplateRenderer { if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) { return '' } + + let extra = attrs || '' + if (asType === 'font') { extra = ` type="font/${extension}" crossorigin` } @@ -185,20 +192,26 @@ 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 }) => { + const hasAttrsFn = typeof getPrefetchLinkAttrs === 'function' + return this.prefetchFiles.map(ref => { + if(hasAttrsFn) { + 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 +238,14 @@ 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 + const hasAttrsFn = typeof getScriptAttrs === 'function' + return needed.map((ref) => { + if(hasAttrsFn) { + ref = getScriptAttrs(ref) + } + const { file, attrs = 'defer' } = ref + return `` }).join('') } else { return '' From a6d171c2700b2dfd4bd312711e06f1c9cd2d1236 Mon Sep 17 00:00:00 2001 From: Clark Du Date: Tue, 11 Feb 2020 19:32:28 +0000 Subject: [PATCH 2/2] fix(ssr): add types for custom attributes functions --- src/server/template-renderer/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/server/template-renderer/index.js b/src/server/template-renderer/index.js index d8106070769..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 { @@ -158,9 +162,8 @@ export default class TemplateRenderer { const files = this.getPreloadFiles(context) if (files.length) { const { getPreloadLinkAttrs, shouldPreload } = this.options - const hasAttrsFn = typeof getPreloadLinkAttrs === 'function' return files.map(ref => { - if(hasAttrsFn) { + if(typeof getPreloadLinkAttrs === 'function') { ref = getPreloadLinkAttrs(ref) } const { file, extension, fileWithoutQuery, asType, attrs } = ref @@ -198,9 +201,8 @@ export default class TemplateRenderer { const alreadyRendered = file => { return usedAsyncFiles && usedAsyncFiles.some(f => f.file === file) } - const hasAttrsFn = typeof getPrefetchLinkAttrs === 'function' return this.prefetchFiles.map(ref => { - if(hasAttrsFn) { + if(typeof getPrefetchLinkAttrs === 'function') { ref = getPrefetchLinkAttrs(ref) } const { file, fileWithoutQuery, asType } = ref @@ -239,9 +241,8 @@ export default class TemplateRenderer { const async = (this.getUsedAsyncFiles(context) || []).filter(({ file }) => isJS(file)) const needed = [initial[0]].concat(async, initial.slice(1)) const { getScriptAttrs } = this.options - const hasAttrsFn = typeof getScriptAttrs === 'function' return needed.map((ref) => { - if(hasAttrsFn) { + if(typeof getScriptAttrs === 'function') { ref = getScriptAttrs(ref) } const { file, attrs = 'defer' } = ref