Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromvuejs/vue

Commit7bc899c

Browse files
committed
feat(ssr): add shouldPrefetch option
closevuejs#5964
1 parentf881dd1 commit7bc899c

File tree

3 files changed

+60
-27
lines changed

3 files changed

+60
-27
lines changed

‎src/server/create-renderer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type RenderOptions = {
2727
inject?:boolean;
2828
basedir?:string;
2929
shouldPreload?:Function;
30+
shouldPrefetch?:Function;
3031
clientManifest?:ClientManifest;
3132
runInNewContext?:boolean|'once';
3233
};
@@ -39,13 +40,15 @@ export function createRenderer ({
3940
inject,
4041
cache,
4142
shouldPreload,
43+
shouldPrefetch,
4244
clientManifest
4345
}:RenderOptions={}):Renderer{
4446
constrender=createRenderFunction(modules,directives,isUnaryTag,cache)
4547
consttemplateRenderer=newTemplateRenderer({
4648
template,
4749
inject,
4850
shouldPreload,
51+
shouldPrefetch,
4952
clientManifest
5053
})
5154

‎src/server/template-renderer/index.js

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type TemplateRendererOptions = {
1515
inject?:boolean;
1616
clientManifest?:ClientManifest;
1717
shouldPreload?:(file:string,type:string)=>boolean;
18+
shouldPrefetch?:(file:string,type:string)=>boolean;
1819
};
1920

2021
exporttypeClientManifest={
@@ -30,7 +31,7 @@ export type ClientManifest = {
3031
}
3132
};
3233

33-
typePreloadFile={
34+
typeResource={
3435
file:string;
3536
extension:string;
3637
fileWithoutQuery:string;
@@ -43,8 +44,8 @@ export default class TemplateRenderer {
4344
parsedTemplate:ParsedTemplate|null;
4445
publicPath:string;
4546
clientManifest:ClientManifest;
46-
preloadFiles:Array<string>;
47-
prefetchFiles:Array<string>;
47+
preloadFiles:Array<Resource>;
48+
prefetchFiles:Array<Resource>;
4849
mapFiles:AsyncFileMapper;
4950

5051
constructor(options:TemplateRendererOptions){
@@ -61,8 +62,8 @@ export default class TemplateRenderer {
6162
constclientManifest=this.clientManifest=options.clientManifest
6263
this.publicPath=clientManifest.publicPath.replace(/\/$/,'')
6364
// preload/prefetch directives
64-
this.preloadFiles=clientManifest.initial
65-
this.prefetchFiles=clientManifest.async
65+
this.preloadFiles=(clientManifest.initial||[]).map(normalizeFile)
66+
this.prefetchFiles=(clientManifest.async||[]).map(normalizeFile)
6667
// initial async chunk mapping
6768
this.mapFiles=createMapper(clientManifest)
6869
}
@@ -125,30 +126,21 @@ export default class TemplateRenderer {
125126
returnthis.renderPreloadLinks(context)+this.renderPrefetchLinks(context)
126127
}
127128

128-
getPreloadFiles(context:Object):Array<PreloadFile>{
129+
getPreloadFiles(context:Object):Array<Resource>{
129130
constusedAsyncFiles=this.getUsedAsyncFiles(context)
130131
if(this.preloadFiles||usedAsyncFiles){
131-
return(this.preloadFiles||[]).concat(usedAsyncFiles||[]).map(file=>{
132-
constwithoutQuery=file.replace(/\?.*/,'')
133-
constextension=path.extname(withoutQuery).slice(1)
134-
return{
135-
file,
136-
extension,
137-
fileWithoutQuery:withoutQuery,
138-
asType:getPreloadType(extension)
139-
}
140-
})
132+
return(this.preloadFiles||[]).concat(usedAsyncFiles||[])
141133
}else{
142134
return[]
143135
}
144136
}
145137

146138
renderPreloadLinks(context:Object):string{
147139
constfiles=this.getPreloadFiles(context)
140+
constshouldPreload=this.options.shouldPreload
148141
if(files.length){
149142
returnfiles.map(({ file, extension, fileWithoutQuery, asType})=>{
150143
letextra=''
151-
constshouldPreload=this.options.shouldPreload
152144
// by default, we only preload scripts or css
153145
if(!shouldPreload&&asType!=='script'&&asType!=='style'){
154146
return''
@@ -174,17 +166,20 @@ export default class TemplateRenderer {
174166
}
175167

176168
renderPrefetchLinks(context:Object):string{
169+
constshouldPrefetch=this.options.shouldPrefetch
177170
if(this.prefetchFiles){
178171
constusedAsyncFiles=this.getUsedAsyncFiles(context)
179172
constalreadyRendered=file=>{
180-
returnusedAsyncFiles&&usedAsyncFiles.some(f=>f===file)
173+
returnusedAsyncFiles&&usedAsyncFiles.some(f=>f.file===file)
181174
}
182-
returnthis.prefetchFiles.map(file=>{
183-
if(!alreadyRendered(file)){
184-
return`<link rel="prefetch" href="${this.publicPath}/${file}">`
185-
}else{
175+
returnthis.prefetchFiles.map(({ file, fileWithoutQuery, asType})=>{
176+
if(shouldPrefetch&&!shouldPrefetch(fileWithoutQuery,asType)){
177+
return''
178+
}
179+
if(alreadyRendered(file)){
186180
return''
187181
}
182+
return`<link rel="prefetch" href="${this.publicPath}/${file}">`
188183
}).join('')
189184
}else{
190185
return''
@@ -205,20 +200,21 @@ export default class TemplateRenderer {
205200

206201
renderScripts(context:Object):string{
207202
if(this.clientManifest){
208-
constinitial=this.clientManifest.initial
203+
constinitial=this.preloadFiles
209204
constasync=this.getUsedAsyncFiles(context)
210205
constneeded=[initial[0]].concat(async||[],initial.slice(1))
211-
returnneeded.filter(isJS).map(file=>{
206+
returnneeded.filter(({ file})=>isJS(file)).map(({file})=>{
212207
return`<script src="${this.publicPath}/${file}" defer></script>`
213208
}).join('')
214209
}else{
215210
return ''
216211
}
217212
}
218213

219-
getUsedAsyncFiles(context:Object): ?Array<string>{
214+
getUsedAsyncFiles(context:Object): ?Array<Resource>{
220215
if(!context._mappedFiles&&context._registeredComponents&&this.mapFiles){
221-
context._mappedFiles=this.mapFiles(Array.from(context._registeredComponents))
216+
constregistered=Array.from(context._registeredComponents)
217+
context._mappedFiles=this.mapFiles(registered).map(normalizeFile)
222218
}
223219
returncontext._mappedFiles
224220
}
@@ -232,6 +228,17 @@ export default class TemplateRenderer {
232228
}
233229
}
234230

231+
functionnormalizeFile(file:string):Resource{
232+
constwithoutQuery=file.replace(/\?.*/,'')
233+
constextension=path.extname(withoutQuery).slice(1)
234+
return{
235+
file,
236+
extension,
237+
fileWithoutQuery:withoutQuery,
238+
asType:getPreloadType(extension)
239+
}
240+
}
241+
235242
functiongetPreloadType(ext:string):string{
236243
if(ext==='js'){
237244
return 'script'

‎test/ssr/ssr-template.spec.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ describe('SSR: template option', () => {
230230
(options.preloadOtherAssets ?`<link rel="preload" href="/test.png" as="image">` :``)+
231231
(options.preloadOtherAssets ?`<link rel="preload" href="/test.woff2" as="font" type="font/woff2" crossorigin>` :``)+
232232
// unused chunks should have prefetch
233-
`<link rel="prefetch" href="/1.js">`+
233+
(options.noPrefetch ?`` :`<link rel="prefetch" href="/1.js">`)+
234234
// css assets should be loaded
235235
`<link rel="stylesheet" href="/test.css">`+
236236
`</head><body>`+
@@ -281,6 +281,29 @@ describe('SSR: template option', () => {
281281
})
282282
})
283283

284+
it('bundleRenderer + renderToStream + clientManifest + shouldPrefetch',done=>{
285+
createRendererWithManifest('split.js',{
286+
runInNewContext,
287+
shouldPrefetch:(file,type)=>{
288+
if(type==='script'){
289+
returnfalse
290+
}
291+
}
292+
},renderer=>{
293+
conststream=renderer.renderToStream({state:{a:1}})
294+
letres=''
295+
stream.on('data',chunk=>{
296+
res+=chunk.toString()
297+
})
298+
stream.on('end',()=>{
299+
expect(res).toContain(expectedHTMLWithManifest({
300+
noPrefetch:true
301+
}))
302+
done()
303+
})
304+
})
305+
})
306+
284307
it('bundleRenderer + renderToString + clientManifest + inject: false',done=>{
285308
createRendererWithManifest('split.js',{
286309
runInNewContext,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp