UNPKG

@atlassian/webresource-webpack-plugin

Version:

Auto-generates web-resource definitions from your webpacked code, for usage in an Atlassian product or plugin.

190 lines 10.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = require("lodash"); const flatMap_1 = __importDefault(require("lodash/flatMap")); const uniq_1 = __importDefault(require("lodash/uniq")); const base_dependencies_1 = require("./deps/base-dependencies"); const compiled_css_1 = require("./helpers/compiled-css"); 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 options WrmPlugin configuration * @param compiler Webpack compiler * @param compilation Webpack compilation * @param dependencyModuleMap map of module identifier -> set of web-resource dependencies * @param resourceModuleMap map of resource identifier -> set of web-resource external resources * @param resourceAssetsMap map of resource identifier -> set of asset files referenced by that resource */ constructor({ assetsUUID, options, compiler, compilation, dependencyModuleMap, resourceModuleMap, resourceAssetsMap, }) { this.assetsUUID = assetsUUID; this.options = options; this.compiler = compiler; this.compilation = compilation; this.dependencyModuleMap = dependencyModuleMap; this.resourceModuleMap = resourceModuleMap; this.resourceAssetsMap = resourceAssetsMap; } getSingleRuntimeFiles() { const files = this.getEntryPoints() .map((entrypoint) => entrypoint.getRuntimeChunk()?.files) .find(Boolean); if (!files) { return []; } return Array.from(files); } getAssetResourceDescriptor() { const assetFiles = (0, WebpackHelpers_1.getAllAssetFiles)(this.compilation); return { attributes: { key: `assets-${this.assetsUUID}` }, resources: assetFiles, }; } getWebresourceKeyForChunk(chunk, transform) { const chunkId = String(chunk.id); const chunkName = chunk.name ? String(chunk.name) : chunkId; // compiled-css is a special chunk generated by @compiled/css - we need to preserve its name if ((0, compiled_css_1.chunkLooksLikeCompiledCss)(chunk)) { return chunkName; } else { return transform(chunkId, chunkName); } } /** * 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 = this.getWebresourceKeyForChunk(c, (_id, name) => `split_${name}`); 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) => { return { attributes: syncSplitChunkDependencyKeyMap.get(c), externalResources: (0, WebpackHelpers_1.getExternalResourcesForChunks)(this.compilation, c, this.resourceModuleMap), resources: (0, WebpackHelpers_1.getResourcesForChunks)(this.compilation, [c], [c], this.resourceAssetsMap), dependencies: (0, uniq_1.default)([ ...(0, base_dependencies_1.getBaseDependencies)(), ...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, c, this.dependencyModuleMap, this.options.providedDependencies), ]), }; }); } getAsyncChunksResourceDescriptors() { return (0, WebpackHelpers_1.getAllAsyncChunks)(this.getEntryPoints()).map((c) => { // async chunk webresource key needs to be a chunk id so that it can be loaded correctly by webpack at runtime const webresourceKey = this.getWebresourceKeyForChunk(c, (id) => id); return { attributes: { key: webresourceKey }, externalResources: (0, WebpackHelpers_1.getExternalResourcesForChunks)(this.compilation, c, this.resourceModuleMap), resources: (0, WebpackHelpers_1.getResourcesForChunks)(this.compilation, [c], [c], this.resourceAssetsMap), dependencies: (0, uniq_1.default)([ ...(0, base_dependencies_1.getBaseDependencies)(), ...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, c, this.dependencyModuleMap, this.options.providedDependencies), ...(0, WebpackHelpers_1.getDependencyForCompiledCss)(this.compilation, c, this.options.pluginKey), ]), 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?.dependency); const dependencyList = [ ...(0, base_dependencies_1.getBaseDependencies)(), ...(0, WebpackHelpers_1.getDependenciesForChunks)(this.compilation, runtimeChunk, this.dependencyModuleMap, this.options.providedDependencies), ...sharedSplitDeps, ]; let additionalChunks = []; if (singleRuntime) { dependencyList.unshift(`${this.options.pluginKey}:${singleRuntimeWebResourceKey}`); } else { additionalChunks = [runtimeChunk]; } 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.getExternalResourcesForChunks)(this.compilation, runtimeChunk, this.resourceModuleMap), resources: (0, WebpackHelpers_1.getResourcesForChunks)(this.compilation, additionalChunks, entrypointChunks, this.resourceAssetsMap), 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 (0, lodash_1.uniqBy)([] .concat(this.getSyncSplitChunksResourceDescriptors()) .concat(this.getAsyncChunksResourceDescriptors()) .concat(this.getEntryPointsResourceDescriptors()) .concat(this.getAssetResourceDescriptor()), 'attributes.key'); } } exports.default = AppResources; //# sourceMappingURL=AppResources.js.map