How
works
Tobias Koppers
About me
• Tobias Koppers
• M. Sc. Computer Science
• Started with Open Source in 2012 as Hobby
• Since 2017: Freelancer (Open Source + Consulting)
• Father of a 2-months old daughter
• Twitter: @wSokra
• Github: @sokra
Agenda
• Walkthrough webpack
• You should get a rough understanding of the implementation of webpack.
• You should know where to look into when customizing.
• We will not go into details of individual optimization algorithms.
• Some unimportant details are omitted for simplicity.
• Some points for customization are highlighted.
• Customization
• You will learn how to write plugins for webpack.
• We won’t list every possible customizable thing.
Plugins
class MyPlugin {
apply(compiler) {
compiler.plugin(“done”, (stats) => {
console.log(stats.toString());
}
}
}
plugins: [ new MyPlugin() ]
Access to nested objects
class MyPlugin {
apply(compiler) {
compiler.plugin(“compilation”, compilation => {
compilation.plugin(“optimize-modules”, modules => {
modules.forEach(…);
}
}
}
}
Hooks
• There are different kind of hooks
• sync
• async (with callback argument)
• sequential
• parallel
• waterfall (passing result to next plugin)
• Check details in code (not all hooks are documented)
• Don’t forget to call the callback!
Elsewise process will exit unexpectedly.
Walkthrough webpack
• webpack is very object-orientated
• Design is probably not perfect
• We start our walkthrough from top down to bottom
• Start: Invoking the CLI: webpack entry.js bundle.js
Command Line Interface
• Get arguments from command line
• Read webpack.config.js
• Invoke exported value if it‘s a function
• Convert command line arguments into configuration
• Call the webpack API with the configuration
• bin/webpack.js, bin/convert-argv.js
• Can‘t be customized
API / webpack facade
• Validates configuration according to schema
• Applies the node.js environment plugins
• Input/Output/Watch FileSystem for node.js
• Calls WebpackOptionsApply to process configuration
• Creates the Compiler
• May call run or watch on the Compiler
• Exports all public plugins to use them in the configuration
WebpackOptionsApply
• Converts all configuration options into plugins
• Applies default plugins
• Examples:
• output.library LibraryTemplatePlugin
• externals ExternalsPlugin
• devtool EvalDevToolModulePlugin,
SourceMapDevToolPlugin, …
• AMDPlugin
• CommonJsPlugin
• RemoveEmptyChunksPlugin
• MergeDuplicateChunksPlugin
Compiler
• run
• compile
• creates Compilation
• emit
• writes assets
• watch Watching
• run
• watch dependencies run again
• All plugins are attached to this instance
Compiler hooks
• (before-)run • compilation
• (before-/after-)compile Compilation
• make • normal-module-factory
NormalModuleFactory
• (after-)emit
• context-module-factory
• done ContextModuleFactory
• watch-run
• invalid
• watch-close
Compilation
• Compiler calls this lifecycle methods of the Compilation:
• addEntry addModuleChain
• finish
• report errors from modules
• seal
Compilation.addModuleChain
• input is a Dependency
• get the ModuleFactory for the Dependency
• ModuleFactory.create returns Module
• Compilation.addModule
• Compilation.buildModule
• Calls Module.build
• Compilation.processModuleDependencies
• foreach unique Dependency in Module
Compilation.addModule
• input is a Module from ModuleFactory
• Return if Module is already in the Compilation (same identifier)
• Check if we have module in cache (same identifier)
• Check if the cached module needs a rebuild
Disconnect Unbuild
• Add module to Compilation.modules list
Compilation.seal
• foreach entrypoint • Ids
• Compilation.addChunk • Modules
• Chunk.addModule • Chunks
• Compilation.processDepBlock- • Record
ForChunk
• Hash
• Optimize
• Modules • Assets
• Chunks • Chunk assets
• Tree • Additional Assets
• Chunk Modules • Optimize Assets
• Sort
Compilation Hooks
• build-module • (after-)seal • after-optimize-chunk-
• failed-module • optimize modules
• succed-module • optimize-modules • optimize-module/chunk-
(-basic/advanced) order
• after-optimize-modules • before-module/chunk-ids
• finish-modules • (after-)optimize-
• optimize-chunks module/chunk-ids
(-basic/advanced)
• chunk-hash • after-optimize-chunks • before/after-hash
• (after-)optimize-tree • additional-(chunk-)assets
• module-asset • optimize-chunk-modules • (after-)optimize-
• chunk-asset (-basic/advanced) (chunk-)assets
ModuleFactory
ModuleFactory
NormalModuleFactory ContextModuleFactory
NormalModuleFactory
• Resolve request (using enhanced-resolve)
• Process rules from RuleSet
• Resolve remaining requests i. e. loaders
• Instanciate NomalModule
• Plugins may alter this process
• Returning other kind of Modules (i. e. externals, dll, ignore)
• Overriding requests
Module
Module
NormalModule ExternalModule
ContextModule DelegatedModule
MultiModule
NormalModule
• Build
• Run loaders using loader-runner
• Store returned Code
• Parse using Parser
• ParserPlugins add dependencies to the DependencyBlock/Module
• Get Source (Code Generation)
• Create a ReplaceSource on top of the stored Code
• Get DependencyTemplate for each Dependency
• Apply templates for Dependency on ReplaceSource
• Templates do string replacements/insertings
Source
Source
ConcatSource
RawSource
CachedSource
OriginalSource
PrefixSource
SourceMapSource
ReplaceSource
Compilation.createAssets
• MainTemplate
• ChunkTemplate
• ModuleTemplate
ModuleTemplate
webpack Facade
Parser
Watching
MainTemplate
Compiler
ChunkTemplate NormalModule
Compilation ModuleFactory
EntryPoint Resolver
NormalModuleFactory
Chunk
RuleSet
Module CommonJsRequire
Dependency
Dependency
ModuleDependency
DependenciesBlock CommonJsRequire
AsyncDependenciesBlock ContextDependency DependencyTemplate
More Info
• Source Code
• github.com/webpack/webpack
• github.com/webpack/webpack-sources
• github.com/webpack/enhanced-resolve
• github.com/webpack/loader-runner
• Documentation
• webpack.js.org
Funding
• webpack needs your help. We are funded by donations. Sponsor?