UNPKG

fusion-cli

Version:
143 lines (124 loc) 3.77 kB
/** Copyright (c) 2018 Uber Technologies, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ /*eslint-env node */ /*:: import type {ClientChunkMetadataState, ClientChunkMetadata} from "../types.js"; */ const assert = require('assert'); class ClientChunkMetadataStateHydrator { /*:: state: ClientChunkMetadataState; */ constructor(state /*: ClientChunkMetadataState*/) { this.state = state; } apply(compiler /*: Object*/) { const name = this.constructor.name; compiler.hooks.invalid.tap(name, () => { this.state.reset(); }); compiler.hooks.thisCompilation.tap(name, (compilation) => { compilation.hooks.afterProcessAssets.tap(name, () => { const chunks = compilation.chunks; const fileManifest = chunkIndexFromWebpackChunks( compilation.chunkGraph, chunks ); const urlMap = chunkMapFromWebpackChunks(chunks); const {criticalPaths, criticalIds} = criticalChunkInfo( compilation, chunks ); this.state.resolve({ fileManifest, urlMap, criticalIds, criticalPaths, ...getChunkInfo(compilation, chunks), }); }); }); } } module.exports = ClientChunkMetadataStateHydrator; function chunkIndexFromWebpackChunks(chunkGraph, chunks) { const chunkIdsByFile = new Map(); for (const c of chunks) { const chunkId = c.id; const files = []; // Iterate through the groups this chunk belongs to, adding the files of the other chunks in that group as well for (const g of c.groupsIterable) { for (const cc of g.chunks) { for (const m of chunkGraph.getChunkModulesIterable(cc)) { if (m.resource) { files.push(m.resource); } else if (m.modules) { files.push(...m.modules.map((module) => module.resource)); } } } } for (const path of files) { if (!chunkIdsByFile.has(path)) { chunkIdsByFile.set(path, new Set()); } const chunkIds = chunkIdsByFile.get(path); if (chunkIds) { chunkIds.add(chunkId); } } } return chunkIdsByFile; } function chunkMapFromWebpackChunks(chunks) { const chunkMap = new Map(); chunks.forEach((chunk) => { const filename = chunk.files.values().next().value; const inner = new Map(); inner.set('es5', filename); chunkMap.set(chunk.id, inner); }); return chunkMap; } function getChunkInfo(compilation, chunks) { assert( compilation.entrypoints.size === 1, `fusion-cli expects there to be a single entrypoint, but there was ${compilation.entrypoints.size}. This is a bug in fusion-cli.` ); const allChunks = new Map(); const runtimeChunkIds = new Set(); const initialChunkIds = new Set(); for (const chunk of chunks) { allChunks.set(chunk.id, chunk.files.values().next().value); if (chunk.hasRuntime()) { runtimeChunkIds.add(chunk.id); } else if (chunk.canBeInitial()) { initialChunkIds.add(chunk.id); } } assert( runtimeChunkIds.size === 1, `fusion-cli expects there to be a single runtime chunk, but there was ${runtimeChunkIds.size}. This is a bug in fusion-cli.` ); return { chunks: allChunks, runtimeChunkIds, initialChunkIds, }; } function criticalChunkInfo(compilation, chunks) { const mainEntrypoint = compilation.entrypoints.get('main'); const chunkIds = mainEntrypoint.chunks.map((c) => c.id); const chunkPaths = mainEntrypoint.chunks.map( (c) => c.files.values().next().value ); return { criticalIds: chunkIds, criticalPaths: chunkPaths, }; }