From 205fdca980f70dba278b59a8fe1bed4ba4a8466c Mon Sep 17 00:00:00 2001 From: LingyuCoder Date: Tue, 13 Aug 2024 16:59:40 +0800 Subject: [PATCH 1/3] docs: add overview flow chart for compilation hooks --- website/components/Columns.tsx | 16 +- website/components/Mermaid.scss | 24 ++ .../en/api/plugin-api/compilation-hooks.mdx | 355 +++++++++++++++++ website/docs/en/config/optimization.mdx | 12 + .../zh/api/plugin-api/compilation-hooks.mdx | 356 ++++++++++++++++++ website/docs/zh/config/optimization.mdx | 12 +- 6 files changed, 770 insertions(+), 5 deletions(-) diff --git a/website/components/Columns.tsx b/website/components/Columns.tsx index 775cd1706c5..014cd0be1f1 100644 --- a/website/components/Columns.tsx +++ b/website/components/Columns.tsx @@ -1,20 +1,23 @@ import { Children } from 'react'; -import type { PropsWithChildren } from 'react'; +import type { CSSProperties, PropsWithChildren } from 'react'; interface Props { titles?: string[]; + styles?: CSSProperties[]; } export default function Columns({ children, titles = [], + styles = [], }: PropsWithChildren) { return (
{Children.map(children, (child, index) => { const title = titles[index]; + const style = styles[index]; return ( - + {child} ); @@ -25,11 +28,16 @@ export default function Columns({ interface ColumnProps { title?: string; + style?: CSSProperties; } -export function Column({ title, children }: PropsWithChildren) { +export function Column({ + title, + children, + style, +}: PropsWithChildren) { return ( -
+
{title &&
{title}
} {children}
diff --git a/website/components/Mermaid.scss b/website/components/Mermaid.scss index e7ae3be7ef2..591601dbe18 100644 --- a/website/components/Mermaid.scss +++ b/website/components/Mermaid.scss @@ -50,6 +50,18 @@ } } + .flow-optimization { + rect, + polygon { + fill: var(--tw-ring-color) !important; + stroke: var(--rp-container-details-link) !important; + } + + span.nodeLabel { + color: #333 !important; + } + } + .flow-hook { rect, polygon { @@ -125,6 +137,18 @@ } } + .flow-optimization { + rect, + polygon { + fill: var(--tw-ring-color) !important; + stroke: var(--rp-container-details-link) !important; + } + + span.nodeLabel { + color: #ccc !important; + } + } + .flow-hook { rect, polygon { diff --git a/website/docs/en/api/plugin-api/compilation-hooks.mdx b/website/docs/en/api/plugin-api/compilation-hooks.mdx index e7c6908485c..d0cde2a367e 100644 --- a/website/docs/en/api/plugin-api/compilation-hooks.mdx +++ b/website/docs/en/api/plugin-api/compilation-hooks.mdx @@ -1,3 +1,4 @@ +import Mermaid from '@components/Mermaid'; import { Badge } from '@theme'; import ModuleType from '../../types/module.mdx'; import ChunkType from '../../types/chunk.mdx'; @@ -6,6 +7,8 @@ import SourceType from '../../types/source.mdx'; import HashType from '../../types/hash.mdx'; import CompilerType from '../../types/compiler.mdx'; import { Collapse, CollapsePanel } from '@components/Collapse'; +import Columns from '@components/Columns'; +import { NoSSR } from 'rspress/runtime'; # Compilation Hooks @@ -13,6 +16,352 @@ import { Collapse, CollapsePanel } from '@components/Collapse'; The main compilation logic of Rspack runs on the Rust side. For factors such as stability, performance, and architecture, after the Rust side compilation objects are transferred to the JavaScript side when using hooks, the modifications on these objects will not be synchronized to the Rust side. Therefore, most of hooks are "read-only". ::: +## Overview + + + + + + + +{` +flowchart TD +EntryPlugin("EntryPlugin") --> AddEntry("compilation.addEntry(callback)") +AddEntry --> HookAddEntry(hooks.addEntry) +subgraph BuildModuleGraph["Create module graph"] +HookAddEntry --> FactorizeModule("ModuleFactory.create()") +FactorizeModule <--> SideEffectsResolve(Tree shaking module side effects) +FactorizeModule <--> Resolve("Resolve module path") + +FactorizeModule --> BuildModule("compilation.buildModule()") +BuildModule --> HookStillValidModule{hooks.stillValidModule} +HookStillValidModule --> |true| ProcessDependencies("Process dependencies") +HookStillValidModule --> |false| HookBuildModule(hooks.buildModule) +HookBuildModule --> ModuleBuild("module.build()") +ModuleBuild --> RunLoaders("Run the loaders") +RunLoaders --> ParserParse("Parse dependencies") +ParserParse --> ModuleBuild +ParserParse <--> InnerGraph(Tree shaking inner graph parsing) +ParserParse <--> SideEffectsCode(Tree shaking code side effects) +ModuleBuild --> |success| HookSucceedModule(hooks.succeedModule) +ModuleBuild --> |failed| HookFailedModule(hooks.failedModule) +HookSucceedModule --> ProcessDependencies +HookFailedModule --> ProcessDependencies +ProcessDependencies --> FactorizeModule +ProcessDependencies --> |failed| HookFailedEntry(hooks.failedEntry) +ProcessDependencies --> |success| HookSucceedEntry(hooks.succeedEntry) +HookFailedEntry --> Callback("callback()") +HookSucceedEntry --> Callback +end + +class AddEntry flow-start +class Callback flow-end +class FactorizeModule,Resolve,BuildModule,ProcessDependencies,RunLoaders,ParserParse,ModuleBuild flow-process +class InnerGraph,SideEffectsResolve,SideEffectsCode flow-optimization +class HookBuildModule,HookSucceedModule flow-hook +class HookStillValidModule,HookAddEntry,HookFailedEntry,HookSucceedEntry,HookFailedModule flow-hook-non-support +`} + + + +
+ + +{` +flowchart TD +CompilerCompile("compiler.compile()") --> CompilationFinish("compilation.finish(callback)") +CompilationFinish --> HookFinishModules(hooks.finishModules) +HookFinishModules <--> FlagDependencyExports(Tree shaking flag module exports) +HookFinishModules --> Callback("callback()") + +class CompilationFinish flow-start +class Callback flow-end +class FlagDependencyExports flow-optimization +class HookFinishModules flow-hook +`} + + + +
+ + + +{` +flowchart TD +StatsToString("stats.toString()") --> CreateStatsOptions("compilation.createStatsOptions") +CreateStatsOptions --> HookStatsPreset(hooks.statsPreset) +HookStatsPreset --> HookStatsNormalize(hooks.statsNormalize) +HookStatsNormalize --> CreateStatsOptions +CreateStatsOptions --> HookStatsFactory(hooks.statsFactory) +HookStatsFactory --> HookStatsPrinter(hooks.statsPrinter) +HookStatsPrinter --> StatsJSON("Generate stats JSON") +StatsJSON --> StatsOutput("Output stats string") + +class StatsToString flow-start +class StatsOutput flow-end +class CreateStatsOptions,StatsJSON flow-process +class HookStatsFactory,HookStatsPrinter,HookStatsPreset,HookStatsNormalize flow-hook +`} + + + +
+ +
+ +
+ + + +{` +flowchart TD +subgraph Start +direction LR +CompilerCompile("compiler.compile()") --> Seal("compilation.seal(callback)") +Seal --> HookSeal(hooks.seal) + +class HookSeal flow-hook +end + +Start --> ChunkGraph + +subgraph ChunkGraph["Create chunk graph"] +direction LR + + subgraph OptimizeDependencies["Optimize module graph"] + direction TB + HooksOptimizationDependencies(hooks.optimizeDependencies) <--> FlagUsedExports(Tree shaking flag used exports) + HooksOptimizationDependencies --> HookAfterOptimizeDependencies(hooks.afterOptimizeDependencies) + + class HooksOptimizationDependencies,HookAfterOptimizeDependencies flow-hook-non-support + class FlagUsedExports flow-optimization + end + + OptimizeDependencies --> GenerateChunkGraph + + subgraph GenerateChunkGraph["Generate chunk graph"] + direction TB + HookBeforeChunks(hooks.beforeChunks) --> CreateEntryChunks("Create entry chunks") + CreateEntryChunks --> BuildChunkGraph("Build chunk graph") + BuildChunkGraph --> HookAfterChunks(hooks.afterChunks) + + class HookBeforeChunks,HookAfterChunks flow-hook-non-support + class CreateEntryChunks,BuildChunkGraph flow-process + class FlagUsedExports flow-optimization + end + +end + +ChunkGraph --> Optimization + +subgraph Optimization["Optimize modules and chunks"] +direction LR + + subgraph OptimizeModules["Optimize modules"] + direction TB + HookOptimize(hooks.optimize) --> HookOptimizeModules(hooks.optimizeModules) + HookOptimizeModules --> HookAfterOptimizeModules(hooks.afterOptimizeModules) + + class HookOptimize flow-hook-non-support + class HookOptimizeModules,HookAfterOptimizeModules flow-hook-partial-support + end + + OptimizeModules --> OptimizeChunks["Optimize chunks"] + + subgraph OptimizeChunks + HookOptimizeChunks(hooks.optimizeChunks) <--> SplitChunks(Split chunks) + HookOptimizeChunks --> HookAfterOptimizeChunks(hooks.afterOptimizeChunks) + + class HookOptimizeChunks,HookAfterOptimizeChunks flow-hook-non-support + class SplitChunks flow-optimization + end + + OptimizeChunks --> OptimizeTree + + subgraph OptimizeTree["Optimize chunk groups"] + HookOptimizeTree(hooks.optimizeTree) --> HookAfterOptimizeTree(hooks.afterOptimizeTree) + + class HookOptimizeTree flow-hook-partial-support + class HookAfterOptimizeTree flow-hook-non-support + end + + OptimizeTree --> OptimizeChunkModules + + subgraph OptimizeChunkModules["Optimize modules in chunks"] + HookOptimizeChunkModules(hooks.optimizeChunkModules) <--> ModuleConcatenation(Module concatenation) + HookOptimizeChunkModules --> HookAfterOptimizeChunkModules(hooks.afterOptimizeChunkModules) + HookAfterOptimizeChunkModules --> HookShouldRecord(hooks.shouldRecord) + + class HookOptimizeChunkModules flow-hook-partial-support + class HookShouldRecord,HookAfterOptimizeChunkModules flow-hook-non-support + class ModuleConcatenation flow-optimization + end + +end + +Optimization --> GenerateIds + +subgraph GenerateIds["Generate IDs of modules and chunks"] +direction LR + + subgraph CreateModuleIds["Generate IDs of modules"] + HookReviveModules(hooks.reviveModules) --> HookBeforeModuleIds(hooks.beforeModuleIds) + HookBeforeModuleIds --> HookModuleIds(hooks.moduleIds) + HookModuleIds --> HookOptimizeModuleIds(hooks.optimizeModuleIds) + HookOptimizeModuleIds --> HookAfterOptimizeModuleIds(hooks.afterOptimizeModuleIds) + + class HookReviveModules,HookModuleIds,HookBeforeModuleIds,HookOptimizeModuleIds,HookAfterOptimizeModuleIds flow-hook-non-support + end + + CreateModuleIds --> CreateChunkIds + + subgraph CreateChunkIds["Generate IDs of chunks"] + HookReviveChunks(hooks.reviveChunks) --> HookBeforeChunkIds(hooks.beforeChunkIds) + HookBeforeChunkIds --> HookChunkIds(hooks.moduleIds) + HookChunkIds --> HookOptimizeChunkIds(hooks.optimizeChunkIds) + HookOptimizeChunkIds --> HookAfterOptimizeChunkIds(hooks.afterOptimizeChunkIds) + + class HookReviveChunks,HookChunkIds,HookBeforeChunkIds,HookOptimizeChunkIds,HookAfterOptimizeChunkIds flow-hook-non-support + end + + CreateChunkIds --> CreateRecords + + subgraph CreateRecords["Generate records"] + ShouldRecord{"shouldRecord"} --> |true| HookRecordModules(hooks.recordModules) + ShouldRecord{"shouldRecord"} --> |false| HookOptimizeCodeGeneration(hooks.optimizeCodeGeneration) + HookRecordModules --> HookRecordChunks(hooks.recordChunks) + HookRecordChunks --> HookOptimizeCodeGeneration(hooks.optimizeCodeOptions) + + class ShouldRecord,HookRecordModules,HookRecordChunks,HookOptimizeCodeGeneration flow-hook-non-support + class SplitChunks flow-optimization + end + +end + +GenerateIds --> CodeGeneration + +subgraph CodeGeneration["Generate code of modules"] +direction LR + + subgraph CreateModuleHashes["Generate hashes of modules"] + HookBeforeModuleHash(hooks.beforeModuleHash) --> GenerateModuleHashes("Create module hashes") + GenerateModuleHashes --> HookAfterModuleHash(hooks.afterModuleHash) + + class HookBeforeModuleHash,HookAfterModuleHash flow-hook-non-support + class GenerateModuleHashes flow-process + end + + CreateModuleHashes --> ModuleGeneration + + subgraph ModuleGeneration["Generate code of modules"] + HookBeforeModuleCodeGeneration(hooks.beforeModuleCodeGeneration) --> ModuleCodeGeneration("Generate module codes") + ModuleCodeGeneration --> HookAfterModuleCodeGeneration(hooks.afterModuleCodeGeneration) + + class HookBeforeModuleCodeGeneration,HookAfterModuleCodeGeneration flow-hook-non-support + class ModuleCodeGeneration flow-process + end + + ModuleGeneration --> CollectRuntimeRequirements + + subgraph CollectRuntimeRequirements["Collect runtime modules"] + HookBeforeRuntime(hooks.beforeRuntimeRequirements) --> HookModuleRuntime(hooks.runtimeRequirementInModule) + HookModuleRuntime --> HookAdditionalChunkRuntime(hooks.additionalChunkRuntimeRequirements) + HookAdditionalChunkRuntime --> HookChunkRuntime(hooks.runtimeRequirementInChunk) + HookChunkRuntime --> HookAdditionalTreeRuntime(hooks.additionalTreeRuntimeRequirements) + HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree) + HookTreeRuntime --> HookAfterRuntimeRequirements(hooks.afterRuntimeRequirements) + HookTreeRuntime <--> HookRuntimeModule(hooks.runtimeModule) + + class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookTreeRuntime,HookAfterRuntimeRequirements, flow-hook-non-support + class HookAdditionalTreeRuntime,HookRuntimeModule flow-hook-partial-support + class ModuleCodeGeneration flow-process + end + + CollectRuntimeRequirements --> CompilationHash + + subgraph CompilationHash["Generate hash of compilation"] + HookBeforeHash(hooks.beforeHash) --> CreateHash("Create compilation hash") + CreateHash --> HookChunkHash(hooks.chunkHash) + HookChunkHash --> HookFullHash(hooks.fullHash) + HookFullHash --> CreateHash + CreateHash --> HookAfterHash(hooks.afterHash) + + class HookBeforeHash,HookAfterHash,HookFullHash flow-hook-non-support + class HookChunkHash flow-hook-partial-support + class CreateHash flow-process + end + +end + +CodeGeneration --> Assets + +subgraph Assets["Generate assets"] +direction LR +subgraph CreateModuleAssets["Generate assets of modules"] +ShouldRecord2{"shouldRecord"} --> |true| HookRecordHash(hooks.recordHash) +HookRecordHash --> HookBeforeModuleAssets(hooks.beforeModuleAssets) +ShouldRecord2{"shouldRecord"} --> |false| HookBeforeModuleAssets +HookBeforeModuleAssets --> GenerateModuleAssets("Generate module assets") +GenerateModuleAssets <--> HookModuleAsset(hooks.moduleAsset) + + class ShouldRecord2,HookRecordHash,HookBeforeModuleAssets,HookModuleAsset flow-hook-non-support + class GenerateModuleAssets flow-process + end + + CreateModuleAssets --> CreateChunkAssets + + subgraph CreateChunkAssets["Generate assets of chunks"] + HookShouldGenerateChunkAssets{hooks.shouldGenerateChunkAssets} --> |true| HookBeforeChunkAssets(hooks.beforeChunkAssets) + HookBeforeChunkAssets --> GenerateChunkAssets("Generate chunk assets") + GenerateChunkAssets --> HookRenderManifest(hooks.renderManifest) + HookRenderManifest --> HookChunkAsset(hooks.chunkAsset) + HookChunkAsset --> GenerateChunkAssets + HookShouldGenerateChunkAssets --> |false| HookProcessAssets(hooks.processAssets) + + class HookBeforeChunkAssets,HookShouldGenerateChunkAssets,HookRenderManifest flow-hook-non-support + class HookChunkAsset flow-hook-partial-support + class HookProcessAssets flow-hook + class GenerateChunkAssets flow-process + end + + CreateChunkAssets --> ProcessAssets + + subgraph ProcessAssets["Process assets"] + HookProcessAssets2(hooks.processAssets) --> HookAfterProcessAssets(hooks.afterProcessAssets) + HookAfterProcessAssets --> |shouldRecord=true| HookRecord(hooks.record) + + class HookProcessAssets2,HookAfterProcessAssets flow-hook + class HookRecord flow-hook-non-support + + end + +end + +Assets --> End + +subgraph End +direction LR +HookNeedAdditionalSeal --> |true| HookUnseal(hooks.unseal) +HookNeedAdditionalSeal --> |false| HookAfterSeal +HookUnseal --> Reseal("compilation.seal()") +HookAfterSeal(hooks.afterSeal) --> Callback("callback()") + +class HookAfterSeal flow-hook +class HookNeedAdditionalSeal,HookUnseal flow-hook-non-support +class Reseal flow-start +end + +End -. additional seal .-> Start + +class Seal flow-start +class Callback flow-end + +`} + + + +
+ ## `buildModule` @@ -109,6 +458,12 @@ Called when all modules have been built without errors. +## `seal` + +Called when the compilation stops accepting new modules and starts to optimize modules. + +- **Type:** `SyncHook<[]>` + ## `optimizeModules` diff --git a/website/docs/en/config/optimization.mdx b/website/docs/en/config/optimization.mdx index 3678e1ac04f..068a85119f6 100644 --- a/website/docs/en/config/optimization.mdx +++ b/website/docs/en/config/optimization.mdx @@ -312,6 +312,18 @@ function f2() { Here we assign the `value` to `value2`. Both `value2` and `value` are accessed within the functions `f2` and `f1` respectively, but the functions are not called, hence `value2` and `value` are not actually used, thus the import of `value` can be removed. +## optimization.concatenateModules + + + +Tells Rspack to find segments of the module graph which can be safely concatenated into a single module. Depends on [optimization.providedExports](#optimizationprovidedexports) and [optimization.usedExports](#optimizationusedexports). By default `optimization.concatenateModules` is enabled in `production` mode and disabled elsewise. + ## optimization.nodeEnv + + + + + +{` +flowchart TD +EntryPlugin("EntryPlugin") --> AddEntry("compilation.addEntry(callback)") +AddEntry --> HookAddEntry(hooks.addEntry) +subgraph BuildModuleGraph["创建模块图"] +HookAddEntry --> FactorizeModule("ModuleFactory.create()") +FactorizeModule <--> SideEffectsResolve(检测模块副作用) +FactorizeModule <--> Resolve("解析模块路径") + +FactorizeModule --> BuildModule("compilation.buildModule()") +BuildModule --> HookStillValidModule{hooks.stillValidModule} +HookStillValidModule --> |true| ProcessDependencies("处理模块依赖") +HookStillValidModule --> |false| HookBuildModule(hooks.buildModule) +HookBuildModule --> ModuleBuild("module.build()") +ModuleBuild --> RunLoaders("运行 Loader 编译模块") +RunLoaders --> ParserParse("解析模块依赖") +ParserParse --> ModuleBuild +ParserParse <--> InnerGraph(分析变量引用) +ParserParse <--> SideEffectsCode(检测代码副作用) +ModuleBuild --> |success| HookSucceedModule(hooks.succeedModule) +ModuleBuild --> |failed| HookFailedModule(hooks.failedModule) +HookSucceedModule --> ProcessDependencies +HookFailedModule --> ProcessDependencies +ProcessDependencies --> FactorizeModule +ProcessDependencies --> |failed| HookFailedEntry(hooks.failedEntry) +ProcessDependencies --> |success| HookSucceedEntry(hooks.succeedEntry) +HookFailedEntry --> Callback("callback()") +HookSucceedEntry --> Callback + +end + +class AddEntry flow-start +class Callback flow-end +class FactorizeModule,Resolve,BuildModule,ProcessDependencies,RunLoaders,ParserParse,ModuleBuild flow-process +class InnerGraph,SideEffectsResolve,SideEffectsCode flow-optimization +class HookBuildModule,HookSucceedModule flow-hook +class HookStillValidModule,HookAddEntry,HookFailedEntry,HookSucceedEntry,HookFailedModule flow-hook-non-support +`} + + + +
+ + +{` +flowchart TD +CompilerCompile("compiler.compile()") --> CompilationFinish("compilation.finish(callback)") +CompilationFinish --> HookFinishModules(hooks.finishModules) +HookFinishModules <--> FlagDependencyExports(分析模块导出) +HookFinishModules --> Callback("callback()") + +class CompilationFinish flow-start +class Callback flow-end +class FlagDependencyExports flow-optimization +class HookFinishModules flow-hook +`} + + + +
+ + + +{` +flowchart TD +StatsToString("stats.toString()") --> CreateStatsOptions("compilation.createStatsOptions") +CreateStatsOptions --> HookStatsPreset(hooks.statsPreset) +HookStatsPreset --> HookStatsNormalize(hooks.statsNormalize) +HookStatsNormalize --> CreateStatsOptions +CreateStatsOptions --> HookStatsFactory(hooks.statsFactory) +HookStatsFactory --> HookStatsPrinter(hooks.statsPrinter) +HookStatsPrinter --> StatsJSON(生成 Stats 对象) +StatsJSON --> StatsOutput("生成 Stats 字符串") + +class StatsToString flow-start +class StatsOutput flow-end +class CreateStatsOptions,StatsJSON flow-process +class HookStatsFactory,HookStatsPrinter,HookStatsPreset,HookStatsNormalize flow-hook +`} + + + +
+ +
+ +
+ + + +{` +flowchart TD +subgraph Start +direction LR +CompilerCompile("compiler.compile()") --> Seal("compilation.seal(callback)") +Seal --> HookSeal(hooks.seal) + +class HookSeal flow-hook +end + +Start --> ChunkGraph + +subgraph ChunkGraph["创建 Chunk 图"] +direction LR + + subgraph OptimizeDependencies["优化模块图"] + direction TB + HooksOptimizationDependencies(hooks.optimizeDependencies) <--> FlagUsedExports(分析被使用的导出) + HooksOptimizationDependencies --> HookAfterOptimizeDependencies(hooks.afterOptimizeDependencies) + + class HooksOptimizationDependencies,HookAfterOptimizeDependencies flow-hook-non-support + class FlagUsedExports flow-optimization + end + + OptimizeDependencies --> GenerateChunkGraph + + subgraph GenerateChunkGraph["生成 Chunk 图"] + direction TB + HookBeforeChunks(hooks.beforeChunks) --> CreateEntryChunks("创建入口 Chunk") + CreateEntryChunks --> BuildChunkGraph("从入口出发生成 Chunk 图") + BuildChunkGraph --> HookAfterChunks(hooks.afterChunks) + + class HookBeforeChunks,HookAfterChunks flow-hook-non-support + class CreateEntryChunks,BuildChunkGraph flow-process + class FlagUsedExports flow-optimization + end + +end + +ChunkGraph --> Optimization + +subgraph Optimization["优化模块和 Chunk"] +direction LR + + subgraph OptimizeModules["优化模块"] + direction TB + HookOptimize(hooks.optimize) --> HookOptimizeModules(hooks.optimizeModules) + HookOptimizeModules --> HookAfterOptimizeModules(hooks.afterOptimizeModules) + + class HookOptimize flow-hook-non-support + class HookOptimizeModules,HookAfterOptimizeModules flow-hook-partial-support + end + + OptimizeModules --> OptimizeChunks["优化 Chunk"] + + subgraph OptimizeChunks + HookOptimizeChunks(hooks.optimizeChunks) <--> SplitChunks(拆分 Chunk 优化) + HookOptimizeChunks --> HookAfterOptimizeChunks(hooks.afterOptimizeChunks) + + class HookOptimizeChunks,HookAfterOptimizeChunks flow-hook-non-support + class SplitChunks flow-optimization + end + + OptimizeChunks --> OptimizeTree + + subgraph OptimizeTree["优化 Chunk 组"] + HookOptimizeTree(hooks.optimizeTree) --> HookAfterOptimizeTree(hooks.afterOptimizeTree) + + class HookOptimizeTree flow-hook-partial-support + class HookAfterOptimizeTree flow-hook-non-support + end + + OptimizeTree --> OptimizeChunkModules + + subgraph OptimizeChunkModules["优化 Chunk 内的模块"] + HookOptimizeChunkModules(hooks.optimizeChunkModules) <--> ModuleConcatenation(合并拼接模块) + HookOptimizeChunkModules --> HookAfterOptimizeChunkModules(hooks.afterOptimizeChunkModules) + HookAfterOptimizeChunkModules --> HookShouldRecord(hooks.shouldRecord) + + class HookOptimizeChunkModules flow-hook-partial-support + class HookShouldRecord,HookAfterOptimizeChunkModules flow-hook-non-support + class ModuleConcatenation flow-optimization + end + +end + +Optimization --> GenerateIds + +subgraph GenerateIds["生成 ID 信息"] +direction LR + + subgraph CreateModuleIds["生成模块 ID"] + HookReviveModules(hooks.reviveModules) --> HookBeforeModuleIds(hooks.beforeModuleIds) + HookBeforeModuleIds --> HookModuleIds(hooks.moduleIds) + HookModuleIds --> HookOptimizeModuleIds(hooks.optimizeModuleIds) + HookOptimizeModuleIds --> HookAfterOptimizeModuleIds(hooks.afterOptimizeModuleIds) + + class HookReviveModules,HookModuleIds,HookBeforeModuleIds,HookOptimizeModuleIds,HookAfterOptimizeModuleIds flow-hook-non-support + end + + CreateModuleIds --> CreateChunkIds + + subgraph CreateChunkIds["生成 Chunk ID"] + HookReviveChunks(hooks.reviveChunks) --> HookBeforeChunkIds(hooks.beforeChunkIds) + HookBeforeChunkIds --> HookChunkIds(hooks.moduleIds) + HookChunkIds --> HookOptimizeChunkIds(hooks.optimizeChunkIds) + HookOptimizeChunkIds --> HookAfterOptimizeChunkIds(hooks.afterOptimizeChunkIds) + + class HookReviveChunks,HookChunkIds,HookBeforeChunkIds,HookOptimizeChunkIds,HookAfterOptimizeChunkIds flow-hook-non-support + end + + CreateChunkIds --> CreateRecords + + subgraph CreateRecords["生成编译记录"] + ShouldRecord{"shouldRecord"} --> |true| HookRecordModules(hooks.recordModules) + ShouldRecord{"shouldRecord"} --> |false| HookOptimizeCodeGeneration(hooks.optimizeCodeGeneration) + HookRecordModules --> HookRecordChunks(hooks.recordChunks) + HookRecordChunks --> HookOptimizeCodeGeneration(hooks.optimizeCodeOptions) + + class ShouldRecord,HookRecordModules,HookRecordChunks,HookOptimizeCodeGeneration flow-hook-non-support + class SplitChunks flow-optimization + end + +end + +GenerateIds --> CodeGeneration + +subgraph CodeGeneration["生成模块和 Chunk 代码"] +direction LR + + subgraph CreateModuleHashes["生成模块哈希"] + HookBeforeModuleHash(hooks.beforeModuleHash) --> GenerateModuleHashes("生成模块哈希") + GenerateModuleHashes --> HookAfterModuleHash(hooks.afterModuleHash) + + class HookBeforeModuleHash,HookAfterModuleHash flow-hook-non-support + class GenerateModuleHashes flow-process + end + + CreateModuleHashes --> ModuleGeneration + + subgraph ModuleGeneration["生成模块代码"] + HookBeforeModuleCodeGeneration(hooks.beforeModuleCodeGeneration) --> ModuleCodeGeneration("生成模块代码") + ModuleCodeGeneration --> HookAfterModuleCodeGeneration(hooks.afterModuleCodeGeneration) + + class HookBeforeModuleCodeGeneration,HookAfterModuleCodeGeneration flow-hook-non-support + class ModuleCodeGeneration flow-process + end + + ModuleGeneration --> CollectRuntimeRequirements + + subgraph CollectRuntimeRequirements["收集运行时模块依赖"] + HookBeforeRuntime(hooks.beforeRuntimeRequirements) --> HookModuleRuntime(hooks.runtimeRequirementInModule) + HookModuleRuntime --> HookAdditionalChunkRuntime(hooks.additionalChunkRuntimeRequirements) + HookAdditionalChunkRuntime --> HookChunkRuntime(hooks.runtimeRequirementInChunk) + HookChunkRuntime --> HookAdditionalTreeRuntime(hooks.additionalTreeRuntimeRequirements) + HookAdditionalTreeRuntime --> HookTreeRuntime(hooks.runtimeRequirementInTree) + HookTreeRuntime --> HookAfterRuntimeRequirements(hooks.afterRuntimeRequirements) + HookTreeRuntime <--> HookRuntimeModule(hooks.runtimeModule) + + class HookBeforeRuntime,HookModuleRuntime,HookAdditionalChunkRuntime,HookChunkRuntime,HookTreeRuntime,HookAfterRuntimeRequirements, flow-hook-non-support + class HookAdditionalTreeRuntime,HookRuntimeModule flow-hook-partial-support + class ModuleCodeGeneration flow-process + end + + CollectRuntimeRequirements --> CompilationHash + + subgraph CompilationHash["生成 Compilation 哈希"] + HookBeforeHash(hooks.beforeHash) --> CreateHash("生成 Compilation 哈希") + CreateHash --> HookChunkHash(hooks.chunkHash) + HookChunkHash --> HookFullHash(hooks.fullHash) + HookFullHash --> CreateHash + CreateHash --> HookAfterHash(hooks.afterHash) + + class HookBeforeHash,HookAfterHash,HookFullHash flow-hook-non-support + class HookChunkHash flow-hook-partial-support + class CreateHash flow-process + end + +end + +CodeGeneration --> Assets + +subgraph Assets["生成产物信息"] +direction LR +subgraph CreateModuleAssets["生成模块产物"] +ShouldRecord2{"shouldRecord"} --> |true| HookRecordHash(hooks.recordHash) +HookRecordHash --> HookBeforeModuleAssets(hooks.beforeModuleAssets) +ShouldRecord2{"shouldRecord"} --> |false| HookBeforeModuleAssets +HookBeforeModuleAssets --> GenerateModuleAssets("生成模块产物") +GenerateModuleAssets <--> HookModuleAsset(hooks.moduleAsset) + + class ShouldRecord2,HookRecordHash,HookBeforeModuleAssets,HookModuleAsset flow-hook-non-support + class GenerateModuleAssets flow-process + end + + CreateModuleAssets --> CreateChunkAssets + + subgraph CreateChunkAssets["生成 Chunk 产物"] + HookShouldGenerateChunkAssets{hooks.shouldGenerateChunkAssets} --> |true| HookBeforeChunkAssets(hooks.beforeChunkAssets) + HookBeforeChunkAssets --> GenerateChunkAssets("生成 Chunk 产物") + GenerateChunkAssets --> HookRenderManifest(hooks.renderManifest) + HookRenderManifest --> HookChunkAsset(hooks.chunkAsset) + HookChunkAsset --> GenerateChunkAssets + HookShouldGenerateChunkAssets --> |false| HookProcessAssets(hooks.processAssets) + + class HookBeforeChunkAssets,HookShouldGenerateChunkAssets,HookRenderManifest flow-hook-non-support + class HookChunkAsset flow-hook-partial-support + class HookProcessAssets flow-hook + class GenerateChunkAssets flow-process + end + + CreateChunkAssets --> ProcessAssets + + subgraph ProcessAssets["加工产物"] + HookProcessAssets2(hooks.processAssets) --> HookAfterProcessAssets(hooks.afterProcessAssets) + HookAfterProcessAssets --> |shouldRecord=true| HookRecord(hooks.record) + + class HookProcessAssets2,HookAfterProcessAssets flow-hook + class HookRecord flow-hook-non-support + + end + +end + +Assets --> End + +subgraph End +direction LR +HookNeedAdditionalSeal --> |true| HookUnseal(hooks.unseal) +HookNeedAdditionalSeal --> |false| HookAfterSeal +HookUnseal --> Reseal("compilation.seal()") +HookAfterSeal(hooks.afterSeal) --> Callback("callback()") + +class HookAfterSeal flow-hook +class HookNeedAdditionalSeal,HookUnseal flow-hook-non-support +class Reseal flow-start +end + +End -. additional seal .-> Start + +class Seal flow-start +class Callback flow-end + +`} + + + + + ## `buildModule` @@ -129,6 +479,12 @@ type ExecuteModuleContext = { +## `seal` + +停止接收新模块并开始优化前触发。 + +- **类型:** `SyncHook<[]>` + ## `afterOptimizeModules` diff --git a/website/docs/zh/config/optimization.mdx b/website/docs/zh/config/optimization.mdx index 83280fc9b07..35d2828edcf 100644 --- a/website/docs/zh/config/optimization.mdx +++ b/website/docs/zh/config/optimization.mdx @@ -306,7 +306,17 @@ function f2() { 这里我们将 `value` 赋值给了 `value2`,`value2` 和 `value` 也分别在函数 `f2` 和 `f1` 中被访问,但函数没有被调用,因此没有使用到 `value2` 和 `value`,因此 `value` 的导入是可以被删除的。 - | +## optimization.concatenateModules + + + +开启模块拼接优化,允许将多个模块拼接成单个模块以降低产物体积,提升压缩效率。此优化需要开启 [optimization.providedExports](#optimizationprovidedexports) and [optimization.usedExports](#optimizationusedexports)。默认情况下,·optimization.concatenateModules· 在 `production` 模式下启用,其它模式则禁用。 ## optimization.nodeEnv From 29af33af9fdb529859ed5a9cba011cc41a893e0b Mon Sep 17 00:00:00 2001 From: LingyuCoder Date: Tue, 13 Aug 2024 17:53:02 +0800 Subject: [PATCH 2/3] docs: add overview flow chart for compilation hooks --- website/components/Mermaid.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/website/components/Mermaid.scss b/website/components/Mermaid.scss index 591601dbe18..2e0408e0a7e 100644 --- a/website/components/Mermaid.scss +++ b/website/components/Mermaid.scss @@ -119,6 +119,13 @@ stroke: #666 !important; fill: #666 !important; } + + .cluster { + rect { + fill: transparent !important; + stroke: #666 !important; + } + } } .dark { From eed647273c968f86f13b4e655a3de2035326ee46 Mon Sep 17 00:00:00 2001 From: harpsealjs Date: Tue, 13 Aug 2024 18:53:41 +0800 Subject: [PATCH 3/3] Update website/docs/zh/config/optimization.mdx Co-authored-by: neverland --- website/docs/zh/config/optimization.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/zh/config/optimization.mdx b/website/docs/zh/config/optimization.mdx index 35d2828edcf..e542b563907 100644 --- a/website/docs/zh/config/optimization.mdx +++ b/website/docs/zh/config/optimization.mdx @@ -316,7 +316,7 @@ function f2() { ]} /> -开启模块拼接优化,允许将多个模块拼接成单个模块以降低产物体积,提升压缩效率。此优化需要开启 [optimization.providedExports](#optimizationprovidedexports) and [optimization.usedExports](#optimizationusedexports)。默认情况下,·optimization.concatenateModules· 在 `production` 模式下启用,其它模式则禁用。 +开启模块拼接优化,允许将多个模块拼接成单个模块以降低产物体积,提升压缩效率。此优化需要开启 [optimization.providedExports](#optimizationprovidedexports) 和 [optimization.usedExports](#optimizationusedexports)。默认情况下,`optimization.concatenateModules` 在 `production` 模式下启用,其它模式则禁用。 ## optimization.nodeEnv