Spaces:
Sleeping
Sleeping
/** | |
* @license | |
* Copyright 2018 Google Inc. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
const defaultOptions = require('./lib/default-options') | |
const determineAsValue = require('./lib/determine-as-value') | |
const doesChunkBelongToHTML = require('./lib/does-chunk-belong-to-html') | |
const extractChunks = require('./lib/extract-chunks') | |
class PreloadPlugin { | |
constructor (options) { | |
this.options = Object.assign({}, defaultOptions, options) | |
} | |
generateLinks (compilation, htmlPluginData) { | |
const options = this.options | |
const extractedChunks = extractChunks({ | |
compilation, | |
optionsInclude: options.include | |
}) | |
const htmlChunks = options.include === 'allAssets' | |
// Handle all chunks. | |
? extractedChunks | |
// Only handle chunks imported by this HtmlWebpackPlugin. | |
: extractedChunks.filter((chunk) => doesChunkBelongToHTML({ | |
chunk, | |
compilation, | |
htmlAssetsChunks: Object.values(htmlPluginData.assets.chunks) | |
})) | |
// Flatten the list of files. | |
const allFiles = htmlChunks.reduce((accumulated, chunk) => { | |
return accumulated.concat(chunk.files) | |
}, []) | |
const uniqueFiles = new Set(allFiles) | |
const filteredFiles = [...uniqueFiles].filter(file => { | |
return ( | |
!this.options.fileWhitelist || | |
this.options.fileWhitelist.some(regex => regex.test(file)) | |
) | |
}).filter(file => { | |
return ( | |
!this.options.fileBlacklist || | |
this.options.fileBlacklist.every(regex => !regex.test(file)) | |
) | |
}) | |
// Sort to ensure the output is predictable. | |
const sortedFilteredFiles = filteredFiles.sort() | |
const links = [] | |
const publicPath = compilation.outputOptions.publicPath || '' | |
for (const file of sortedFilteredFiles) { | |
const href = `${publicPath}${file}` | |
const attributes = { | |
href, | |
rel: options.rel | |
} | |
// If we're preloading this resource (as opposed to prefetching), | |
// then we need to set the 'as' attribute correctly. | |
if (options.rel === 'preload') { | |
attributes.as = determineAsValue({ | |
href, | |
file, | |
optionsAs: options.as | |
}) | |
// On the off chance that we have a cross-origin 'href' attribute, | |
// set crossOrigin on the <link> to trigger CORS mode. Non-CORS | |
// fonts can't be used. | |
if (attributes.as === 'font') { | |
attributes.crossorigin = '' | |
} | |
} | |
links.push({ | |
tagName: 'link', | |
attributes | |
}) | |
} | |
this.resourceHints = links | |
return htmlPluginData | |
} | |
apply (compiler) { | |
const skip = data => { | |
const htmlFilename = data.plugin.options.filename | |
const exclude = this.options.excludeHtmlNames | |
const include = this.options.includeHtmlNames | |
return ( | |
(include && !(include.includes(htmlFilename))) || | |
(exclude && exclude.includes(htmlFilename)) | |
) | |
} | |
compiler.hooks.compilation.tap( | |
this.constructor.name, | |
compilation => { | |
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap( | |
this.constructor.name, | |
(htmlPluginData) => { | |
if (skip(htmlPluginData)) { | |
return | |
} | |
this.generateLinks(compilation, htmlPluginData) | |
} | |
) | |
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap( | |
this.constructor.name, | |
(htmlPluginData) => { | |
if (skip(htmlPluginData)) { | |
return | |
} | |
if (this.resourceHints) { | |
htmlPluginData.head = [ | |
...this.resourceHints, | |
...htmlPluginData.head | |
] | |
} | |
return htmlPluginData | |
} | |
) | |
} | |
) | |
} | |
} | |
module.exports = PreloadPlugin | |