UNPKG

webpack

Version:

Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

203 lines (190 loc) 6.07 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const { ConcatSource } = require("webpack-sources"); const { RuntimeGlobals } = require(".."); const HotUpdateChunk = require("../HotUpdateChunk"); const Template = require("../Template"); const { getAllChunks } = require("../javascript/ChunkHelpers"); const { getCompilationHooks, getChunkFilenameTemplate } = require("../javascript/JavascriptModulesPlugin"); const { updateHashForEntryStartup } = require("../javascript/StartupHelpers"); /** @typedef {import("../Compiler")} Compiler */ class ModuleChunkFormatPlugin { /** * Apply the plugin * @param {Compiler} compiler the compiler instance * @returns {void} */ apply(compiler) { compiler.hooks.thisCompilation.tap( "ModuleChunkFormatPlugin", compilation => { compilation.hooks.additionalChunkRuntimeRequirements.tap( "ModuleChunkFormatPlugin", (chunk, set) => { if (chunk.hasRuntime()) return; if (compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0) { set.add(RuntimeGlobals.require); set.add(RuntimeGlobals.startupEntrypoint); set.add(RuntimeGlobals.externalInstallChunk); } } ); const hooks = getCompilationHooks(compilation); hooks.renderChunk.tap( "ModuleChunkFormatPlugin", (modules, renderContext) => { const { chunk, chunkGraph, runtimeTemplate } = renderContext; const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null; const source = new ConcatSource(); if (hotUpdateChunk) { throw new Error( "HMR is not implemented for module chunk format yet" ); } else { source.add(`export const id = ${JSON.stringify(chunk.id)};\n`); source.add(`export const ids = ${JSON.stringify(chunk.ids)};\n`); source.add(`export const modules = `); source.add(modules); source.add(`;\n`); const runtimeModules = chunkGraph.getChunkRuntimeModulesInOrder(chunk); if (runtimeModules.length > 0) { source.add("export const runtime =\n"); source.add( Template.renderChunkRuntimeModules( runtimeModules, renderContext ) ); } const entries = Array.from( chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk) ); if (entries.length > 0) { const runtimeChunk = entries[0][1].getRuntimeChunk(); const currentOutputName = compilation .getPath( getChunkFilenameTemplate(chunk, compilation.outputOptions), { chunk, contentHashType: "javascript" } ) .split("/"); // remove filename, we only need the directory currentOutputName.pop(); const getRelativePath = chunk => { const baseOutputName = currentOutputName.slice(); const chunkOutputName = compilation .getPath( getChunkFilenameTemplate( chunk, compilation.outputOptions ), { chunk: chunk, contentHashType: "javascript" } ) .split("/"); // remove common parts while ( baseOutputName.length > 0 && chunkOutputName.length > 0 && baseOutputName[0] === chunkOutputName[0] ) { baseOutputName.shift(); chunkOutputName.shift(); } // create final path return ( (baseOutputName.length > 0 ? "../".repeat(baseOutputName.length) : "./") + chunkOutputName.join("/") ); }; const entrySource = new ConcatSource(); entrySource.add(source); entrySource.add(";\n\n// load runtime\n"); entrySource.add( `import __webpack_require__ from ${JSON.stringify( getRelativePath(runtimeChunk) )};\n` ); const startupSource = new ConcatSource(); startupSource.add( `var __webpack_exec__ = ${runtimeTemplate.returningFunction( `__webpack_require__(${RuntimeGlobals.entryModuleId} = moduleId)`, "moduleId" )}\n` ); const loadedChunks = new Set(); let index = 0; for (let i = 0; i < entries.length; i++) { const [module, entrypoint] = entries[i]; const final = i + 1 === entries.length; const moduleId = chunkGraph.getModuleId(module); const chunks = getAllChunks( entrypoint, runtimeChunk, undefined ); for (const chunk of chunks) { if (loadedChunks.has(chunk)) continue; loadedChunks.add(chunk); startupSource.add( `import * as __webpack_chunk_${index}__ from ${JSON.stringify( getRelativePath(chunk) )};\n` ); startupSource.add( `${RuntimeGlobals.externalInstallChunk}(__webpack_chunk_${index}__);\n` ); index++; } startupSource.add( `${ final ? "var __webpack_exports__ = " : "" }__webpack_exec__(${JSON.stringify(moduleId)});\n` ); } entrySource.add( hooks.renderStartup.call( startupSource, entries[entries.length - 1][0], { ...renderContext, inlined: false } ) ); return entrySource; } } return source; } ); hooks.chunkHash.tap( "ModuleChunkFormatPlugin", (chunk, hash, { chunkGraph, runtimeTemplate }) => { if (chunk.hasRuntime()) return; hash.update("ModuleChunkFormatPlugin"); hash.update("1"); const entries = Array.from( chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk) ); updateHashForEntryStartup(hash, chunkGraph, entries, chunk); } ); } ); } } module.exports = ModuleChunkFormatPlugin;