atlassian-webresource-webpack-plugin
Version:
Auto-generates web-resource definitions from your webpacked code, for usage in an Atlassian product or plugin.
171 lines • 9.08 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const flatMap_1 = __importDefault(require("lodash/flatMap"));
const uniq_1 = __importDefault(require("lodash/uniq"));
const base_dependencies_1 = require("./deps/base-dependencies");
const web_resource_entrypoints_1 = require("./helpers/web-resource-entrypoints");
const WebpackHelpers_1 = require("./WebpackHelpers");
const RUNTIME_WR_KEY = 'common-runtime';
class AppResources {
/**
* @param assetsUUID unique hash to identify the assets web-resource
* @param assetNames full module filepaths -> relative filepath
* @param options WrmPlugin configuration
* @param compiler Webpack compiler
* @param compilation Webpack compilation
*/
constructor({ assetsUUID, assetNames, options, compiler, compilation }) {
this.assetsUUID = assetsUUID;
this.assetNames = assetNames;
this.options = options;
this.compiler = compiler;
this.compilation = compilation;
}
getSingleRuntimeFiles() {
const files = this.getEntryPoints()
.map((entrypoint) => { var _a; return (_a = entrypoint.getRuntimeChunk()) === null || _a === void 0 ? void 0 : _a.files; })
.find(Boolean);
if (!files) {
return [];
}
return Array.from(files);
}
getAssetResourceDescriptor() {
// remove anything that we know is handled differently
const assetFiles = Object.keys(this.compilation.assets).filter((p) => !/\.(js|css|soy)(\.map)?$/.test(p));
return {
attributes: { key: `assets-${this.assetsUUID}` },
resources: assetFiles,
};
}
getDependencyResourcesFromChunk(chunk) {
return Array.from(chunk.auxiliaryFiles);
}
/**
* Every entrypoint has an attribute called "chunks".
* This contains all chunks that are needed to successfully "load" this entrypoint.
* Usually every entrypoint only contains one chunk - the bundle that is build for that entrypoint.
* If more than one chunk is present that means they are split-chunks that contain code needed by the entrypoint to function.
* To get all split chunks we need to get all but the entrypoints "runtimeChunk" which is the chunk solely containing code for this entrypoint and its runtime.
*
* IMPORTANT-NOTE: async-chunks required by this entrypoint are not specified in these chunks but in the childGroups of the entry and/or split chunks.
*/
getSyncSplitChunks() {
const syncSplitChunks = (0, flatMap_1.default)(this.getEntryPoints(), (e) => e.chunks.filter((c) => c !== e.getRuntimeChunk()));
return (0, uniq_1.default)(syncSplitChunks);
}
/**
* Create a key and the fully-qualified web-resource descriptor for every split chunk.
* This is needed to point to reference these chunks as dependency in the entrypoint chunks
*
* <web-resource>
* ...
* <dependency>this-plugin-key:split_some_chunk</dependency>
* ...
* </web-resource>
*/
getSyncSplitChunkDependenciesKeyMap(syncSplitChunks) {
const syncSplitChunkDependencyKeyMap = new Map();
for (const c of syncSplitChunks) {
const webResourceKey = `split_${c.name || c.id}`;
syncSplitChunkDependencyKeyMap.set(c, {
key: webResourceKey,
dependency: `${this.options.pluginKey}:${webResourceKey}`,
});
}
return syncSplitChunkDependencyKeyMap;
}
getSyncSplitChunksResourceDescriptors() {
const syncSplitChunks = this.getSyncSplitChunks();
const syncSplitChunkDependencyKeyMap = this.getSyncSplitChunkDependenciesKeyMap(syncSplitChunks);
/**
* Create descriptors for the split chunk web-resources that have to be created.
* These include - like other chunk-descriptors their assets and external resources etc.
*/
return syncSplitChunks.map((c) => {
const additionalFileDeps = this.getDependencyResourcesFromChunk(c);
return {
attributes: syncSplitChunkDependencyKeyMap.get(c),
externalResources: (0, WebpackHelpers_1.getExternalResourcesForChunk)(this.compilation, c),
resources: (0, uniq_1.default)([...c.files, ...additionalFileDeps]),
dependencies: (0, uniq_1.default)([...(0, base_dependencies_1.getBaseDependencies)(), ...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, c)]),
};
});
}
getAsyncChunksResourceDescriptors() {
return (0, WebpackHelpers_1.getAllAsyncChunks)(this.getEntryPoints()).map((c) => {
const additionalFileDeps = this.getDependencyResourcesFromChunk(c);
return {
attributes: { key: `${c.id}` },
externalResources: (0, WebpackHelpers_1.getExternalResourcesForChunk)(this.compilation, c),
resources: (0, uniq_1.default)([...c.files, ...additionalFileDeps]),
dependencies: (0, uniq_1.default)([...(0, base_dependencies_1.getBaseDependencies)(), ...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, c)]),
contexts: this.options.addAsyncNameAsContext && c.name ? [`async-chunk-${c.name}`] : undefined,
};
});
}
getEntryPoints() {
return Array.from(this.compilation.entrypoints.values());
}
getEntryPointsResourceDescriptors() {
const singleRuntime = (0, WebpackHelpers_1.isSingleRuntime)(this.compiler);
const syncSplitChunks = this.getSyncSplitChunks();
const syncSplitChunkDependencyKeyMap = this.getSyncSplitChunkDependenciesKeyMap(syncSplitChunks);
const singleRuntimeWebResourceKey = this.options.singleRuntimeWebResourceKey || RUNTIME_WR_KEY;
// Used in prod
const prodEntryPoints = this.getEntryPoints().map((entrypoint) => {
const name = entrypoint.name;
const webResourceAttrs = (0, web_resource_entrypoints_1.getWebresourceAttributesForEntry)(name, this.options.webresourceKeyMap);
const entrypointChunks = entrypoint.chunks;
const runtimeChunk = entrypoint.getRuntimeChunk();
// Retrieve all split chunks this entrypoint depends on. These must be added as "<dependency>"s to the web-resource of this entrypoint
const sharedSplitDeps = entrypointChunks
.map((c) => syncSplitChunkDependencyKeyMap.get(c))
.filter(Boolean)
.map((val) => val === null || val === void 0 ? void 0 : val.dependency);
// Construct the list of resources to add to this web-resource
const resourceList = (0, flatMap_1.default)(entrypointChunks, (c) => this.getDependencyResourcesFromChunk(c));
const dependencyList = [
...(0, base_dependencies_1.getBaseDependencies)(),
...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, runtimeChunk),
...sharedSplitDeps,
];
if (singleRuntime) {
dependencyList.unshift(`${this.options.pluginKey}:${singleRuntimeWebResourceKey}`);
}
else {
resourceList.unshift(...runtimeChunk.files);
}
return {
attributes: webResourceAttrs,
contexts: (0, web_resource_entrypoints_1.getContextForEntry)(name, this.options.contextMap, this.options.addEntrypointNameAsContext),
conditions: (0, web_resource_entrypoints_1.getConditionForEntry)(name, this.options.conditionMap),
dataProviders: (0, web_resource_entrypoints_1.getDataProvidersForEntry)(name, this.options.dataProvidersMap),
deprecationInfo: (0, web_resource_entrypoints_1.getDeprecationInfoForEntry)(name, this.options.deprecatedEntrypoints),
externalResources: (0, WebpackHelpers_1.getExternalResourcesForChunk)(this.compilation, runtimeChunk),
resources: (0, uniq_1.default)(resourceList),
dependencies: (0, uniq_1.default)(dependencyList).filter(Boolean),
};
});
if (singleRuntime) {
prodEntryPoints.push({
attributes: { key: singleRuntimeWebResourceKey },
dependencies: (0, base_dependencies_1.getBaseDependencies)(),
resources: this.getSingleRuntimeFiles(),
});
}
return prodEntryPoints;
}
getResourceDescriptors() {
return []
.concat(this.getSyncSplitChunksResourceDescriptors())
.concat(this.getAsyncChunksResourceDescriptors())
.concat(this.getEntryPointsResourceDescriptors())
.concat(this.getAssetResourceDescriptor());
}
}
exports.default = AppResources;
//# sourceMappingURL=AppResources.js.map