Spaces:
Running
Running
| /** | |
| * @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 | |