mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-23 00:45:16 +00:00
208 lines
6.7 KiB
JavaScript
208 lines
6.7 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
/*
|
||
|
Copyright 2018 Google LLC
|
||
|
|
||
|
Use of this source code is governed by an MIT-style
|
||
|
license that can be found in the LICENSE file or at
|
||
|
https://opensource.org/licenses/MIT.
|
||
|
*/
|
||
|
const {
|
||
|
matchPart
|
||
|
} = require('webpack').ModuleFilenameHelpers;
|
||
|
|
||
|
const transformManifest = require('workbox-build/build/lib/transform-manifest');
|
||
|
|
||
|
const getAssetHash = require('./get-asset-hash');
|
||
|
|
||
|
const resolveWebpackURL = require('./resolve-webpack-url');
|
||
|
/**
|
||
|
* For a given asset, checks whether at least one of the conditions matches.
|
||
|
*
|
||
|
* @param {Asset} asset The webpack asset in question. This will be passed
|
||
|
* to any functions that are listed as conditions.
|
||
|
* @param {Compilation} compilation The webpack compilation. This will be passed
|
||
|
* to any functions that are listed as conditions.
|
||
|
* @param {Array<string|RegExp|Function>} conditions
|
||
|
* @return {boolean} Whether or not at least one condition matches.
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
|
||
|
function checkConditions(asset, compilation, conditions = []) {
|
||
|
for (const condition of conditions) {
|
||
|
if (typeof condition === 'function') {
|
||
|
if (condition({
|
||
|
asset,
|
||
|
compilation
|
||
|
})) {
|
||
|
return true;
|
||
|
}
|
||
|
} else {
|
||
|
if (matchPart(asset.name, condition)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
} // We'll only get here if none of the conditions applied.
|
||
|
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
/**
|
||
|
* Creates a mapping of an asset name to an Set of zero or more chunk names
|
||
|
* that the asset is associated with.
|
||
|
*
|
||
|
* Those chunk names come from a combination of the `chunkName` property on the
|
||
|
* asset, as well as the `stats.namedChunkGroups` property. That is the only
|
||
|
* way to find out if an asset has an implicit descendent relationship with a
|
||
|
* chunk, if it was, e.g., created by `SplitChunksPlugin`.
|
||
|
*
|
||
|
* See https://github.com/GoogleChrome/workbox/issues/1859
|
||
|
* See https://github.com/webpack/webpack/issues/7073
|
||
|
*
|
||
|
* @param {Object} stats The webpack compilation stats.
|
||
|
* @return {object<string, Set<string>>}
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
|
||
|
function assetToChunkNameMapping(stats) {
|
||
|
const mapping = {};
|
||
|
|
||
|
for (const asset of stats.assets) {
|
||
|
mapping[asset.name] = new Set(asset.chunkNames);
|
||
|
}
|
||
|
|
||
|
for (const [chunkName, {
|
||
|
assets
|
||
|
}] of Object.entries(stats.namedChunkGroups)) {
|
||
|
for (const assetName of assets) {
|
||
|
// See https://github.com/GoogleChrome/workbox/issues/2194
|
||
|
if (mapping[assetName]) {
|
||
|
mapping[assetName].add(chunkName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return mapping;
|
||
|
}
|
||
|
/**
|
||
|
* Filters the set of assets out, based on the configuration options provided:
|
||
|
* - chunks and excludeChunks, for chunkName-based criteria.
|
||
|
* - include and exclude, for more general criteria.
|
||
|
*
|
||
|
* @param {Compilation} compilation The webpack compilation.
|
||
|
* @param {Object} config The validated configuration, obtained from the plugin.
|
||
|
* @return {Set<Asset>} The assets that should be included in the manifest,
|
||
|
* based on the criteria provided.
|
||
|
* @private
|
||
|
*/
|
||
|
|
||
|
|
||
|
function filterAssets(compilation, config) {
|
||
|
const filteredAssets = new Set(); // See https://webpack.js.org/configuration/stats/#stats
|
||
|
// We only need assets and chunkGroups here.
|
||
|
|
||
|
const stats = compilation.getStats().toJson({
|
||
|
assets: true,
|
||
|
chunkGroups: true
|
||
|
});
|
||
|
const assetNameToChunkNames = assetToChunkNameMapping(stats); // See https://github.com/GoogleChrome/workbox/issues/1287
|
||
|
|
||
|
if (Array.isArray(config.chunks)) {
|
||
|
for (const chunk of config.chunks) {
|
||
|
if (!(chunk in stats.namedChunkGroups)) {
|
||
|
compilation.warnings.push(`The chunk '${chunk}' was provided in ` + `your Workbox chunks config, but was not found in the compilation.`);
|
||
|
}
|
||
|
}
|
||
|
} // See https://webpack.js.org/api/stats/#asset-objects
|
||
|
|
||
|
|
||
|
for (const asset of stats.assets) {
|
||
|
// chunkName based filtering is funky because:
|
||
|
// - Each asset might belong to one or more chunkNames.
|
||
|
// - If *any* of those chunk names match our config.excludeChunks,
|
||
|
// then we skip that asset.
|
||
|
// - If the config.chunks is defined *and* there's no match
|
||
|
// between at least one of the chunkNames and one entry, then
|
||
|
// we skip that assets as well.
|
||
|
const isExcludedChunk = Array.isArray(config.excludeChunks) && config.excludeChunks.some(chunkName => {
|
||
|
return assetNameToChunkNames[asset.name].has(chunkName);
|
||
|
});
|
||
|
|
||
|
if (isExcludedChunk) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
const isIncludedChunk = !Array.isArray(config.chunks) || config.chunks.some(chunkName => {
|
||
|
return assetNameToChunkNames[asset.name].has(chunkName);
|
||
|
});
|
||
|
|
||
|
if (!isIncludedChunk) {
|
||
|
continue;
|
||
|
} // Next, check asset-level checks via includes/excludes:
|
||
|
|
||
|
|
||
|
const isExcluded = checkConditions(asset, compilation, config.exclude);
|
||
|
|
||
|
if (isExcluded) {
|
||
|
continue;
|
||
|
} // Treat an empty config.includes as an implicit inclusion.
|
||
|
|
||
|
|
||
|
const isIncluded = !Array.isArray(config.include) || checkConditions(asset, compilation, config.include);
|
||
|
|
||
|
if (!isIncluded) {
|
||
|
continue;
|
||
|
} // If we've gotten this far, then add the asset.
|
||
|
|
||
|
|
||
|
filteredAssets.add(asset);
|
||
|
}
|
||
|
|
||
|
return filteredAssets;
|
||
|
}
|
||
|
|
||
|
module.exports = async (compilation, config) => {
|
||
|
const filteredAssets = filterAssets(compilation, config);
|
||
|
const {
|
||
|
publicPath
|
||
|
} = compilation.options.output;
|
||
|
const fileDetails = [];
|
||
|
|
||
|
for (const asset of filteredAssets) {
|
||
|
// Not sure why this would be false, but checking just in case, since
|
||
|
// our original list of assets comes from compilation.getStats().toJson(),
|
||
|
// not from compilation.assets.
|
||
|
if (asset.name in compilation.assets) {
|
||
|
// This matches the format expected by transformManifest().
|
||
|
fileDetails.push({
|
||
|
file: resolveWebpackURL(publicPath, asset.name),
|
||
|
hash: getAssetHash(compilation.assets[asset.name]),
|
||
|
size: asset.size || 0
|
||
|
});
|
||
|
} else {
|
||
|
compilation.warnings.push(`Could not precache ${asset.name}, as it's ` + `missing from compilation.assets. Please open a bug against Workbox ` + `with details about your webpack config.`);
|
||
|
}
|
||
|
} // We also get back `size` and `count`, and it would be nice to log that
|
||
|
// somewhere, but... webpack doesn't offer info-level logs?
|
||
|
// https://github.com/webpack/webpack/issues/3996
|
||
|
|
||
|
|
||
|
const {
|
||
|
manifestEntries,
|
||
|
warnings
|
||
|
} = await transformManifest({
|
||
|
fileDetails,
|
||
|
additionalManifestEntries: config.additionalManifestEntries,
|
||
|
dontCacheBustURLsMatching: config.dontCacheBustURLsMatching,
|
||
|
manifestTransforms: config.manifestTransforms,
|
||
|
maximumFileSizeToCacheInBytes: config.maximumFileSizeToCacheInBytes,
|
||
|
modifyURLPrefix: config.modifyURLPrefix,
|
||
|
transformParam: compilation
|
||
|
});
|
||
|
compilation.warnings = compilation.warnings.concat(warnings || []); // Ensure that the entries are properly sorted by URL.
|
||
|
|
||
|
const sortedEntries = manifestEntries.sort((a, b) => a.url === b.url ? 0 : a.url > b.url ? 1 : -1);
|
||
|
return sortedEntries;
|
||
|
};
|