get-manifest-entries-from-compilation.js
7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getManifestEntriesFromCompilation = void 0;
const webpack_1 = require("webpack");
const transform_manifest_1 = require("workbox-build/build/lib/transform-manifest");
const get_asset_hash_1 = require("./get-asset-hash");
const resolve_webpack_url_1 = 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') {
return condition({ asset, compilation });
//return compilation !== null;
}
else {
if (webpack_1.ModuleFilenameHelpers.matchPart(asset.name, condition)) {
return true;
}
}
}
// We'll only get here if none of the conditions applied.
return false;
}
/**
* Returns the names of all the assets in all the chunks in a chunk group,
* if provided a chunk group name.
* Otherwise, if provided a chunk name, return all the assets in that chunk.
* Otherwise, if there isn't a chunk group or chunk with that name, return null.
*
* @param {Compilation} compilation
* @param {string} chunkOrGroup
* @return {Array<string>|null}
* @private
*/
function getNamesOfAssetsInChunkOrGroup(compilation, chunkOrGroup) {
const chunkGroup = compilation.namedChunkGroups &&
compilation.namedChunkGroups.get(chunkOrGroup);
if (chunkGroup) {
const assetNames = [];
for (const chunk of chunkGroup.chunks) {
assetNames.push(...getNamesOfAssetsInChunk(chunk));
}
return assetNames;
}
else {
const chunk = compilation.namedChunks && compilation.namedChunks.get(chunkOrGroup);
if (chunk) {
return getNamesOfAssetsInChunk(chunk);
}
}
// If we get here, there's no chunkGroup or chunk with that name.
return null;
}
/**
* Returns the names of all the assets in a chunk.
*
* @param {Chunk} chunk
* @return {Array<string>}
* @private
*/
function getNamesOfAssetsInChunk(chunk) {
const assetNames = [];
assetNames.push(...chunk.files);
// This only appears to be set in webpack v5.
if (chunk.auxiliaryFiles) {
assetNames.push(...chunk.auxiliaryFiles);
}
return assetNames;
}
/**
* 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();
const assets = compilation.getAssets();
const allowedAssetNames = new Set();
// See https://github.com/GoogleChrome/workbox/issues/1287
if (Array.isArray(config.chunks)) {
for (const name of config.chunks) {
// See https://github.com/GoogleChrome/workbox/issues/2717
const assetsInChunkOrGroup = getNamesOfAssetsInChunkOrGroup(compilation, name);
if (assetsInChunkOrGroup) {
for (const assetName of assetsInChunkOrGroup) {
allowedAssetNames.add(assetName);
}
}
else {
compilation.warnings.push(new Error(`The chunk '${name}' was ` +
`provided in your Workbox chunks config, but was not found in the ` +
`compilation.`));
}
}
}
const deniedAssetNames = new Set();
if (Array.isArray(config.excludeChunks)) {
for (const name of config.excludeChunks) {
// See https://github.com/GoogleChrome/workbox/issues/2717
const assetsInChunkOrGroup = getNamesOfAssetsInChunkOrGroup(compilation, name);
if (assetsInChunkOrGroup) {
for (const assetName of assetsInChunkOrGroup) {
deniedAssetNames.add(assetName);
}
} // Don't warn if the chunk group isn't found.
}
}
for (const asset of assets) {
// chunk based filtering is funky because:
// - Each asset might belong to one or more chunks.
// - 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.
if (deniedAssetNames.has(asset.name)) {
continue;
}
if (Array.isArray(config.chunks) && !allowedAssetNames.has(asset.name)) {
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;
}
async function getManifestEntriesFromCompilation(compilation, config) {
const filteredAssets = filterAssets(compilation, config);
const { publicPath } = compilation.options.output;
const fileDetails = Array.from(filteredAssets).map((asset) => {
return {
file: (0, resolve_webpack_url_1.resolveWebpackURL)(publicPath, asset.name),
hash: (0, get_asset_hash_1.getAssetHash)(asset),
size: asset.source.size() || 0,
};
});
const { manifestEntries, size, warnings } = await (0, transform_manifest_1.transformManifest)({
fileDetails,
additionalManifestEntries: config.additionalManifestEntries,
dontCacheBustURLsMatching: config.dontCacheBustURLsMatching,
manifestTransforms: config.manifestTransforms,
maximumFileSizeToCacheInBytes: config.maximumFileSizeToCacheInBytes,
modifyURLPrefix: config.modifyURLPrefix,
transformParam: compilation,
});
// See https://github.com/GoogleChrome/workbox/issues/2790
for (const warning of warnings) {
compilation.warnings.push(new Error(warning));
}
// 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 { size, sortedEntries };
}
exports.getManifestEntriesFromCompilation = getManifestEntriesFromCompilation;