Frontend Development 18 min read

Understanding Webpack Module Creation: Stages and Dependency Handling

Webpack transforms entry files into modules through four stages—create, add, build, and processDep—where it generates a module instance via factory hooks, registers it in the compilation, runs loaders and parses the source into an AST, groups and resolves dependencies, and finally prepares the modules for bundling.

Didi Tech
Didi Tech
Didi Tech
Understanding Webpack Module Creation: Stages and Dependency Handling

In the previous article we explained how webpack locates entry files. This article describes how those files are transformed into modules.

The overall process can be divided into four stages: create , add , build , and processDep .

1. create

During the create stage webpack generates a module instance. The core logic is in NormalModuleFactory.create which triggers beforeResolve and factory hooks.

create(data, callback) {
  // ... omitted logic
  this.hooks.beforeResolve.callAsync({ contextInfo, resolveOptions, context, request, dependencies }, (err, result) => {
    const factory = this.hooks.factory.call(null);
    if (!factory) return callback();
    factory(result, (err, module) => {
      callback(null, module);
    });
  });
}

2. addModule

After a module instance is created it is stored in Compilation.modules and the internal _modules map. The entry module also receives a reason (e.g., SingleEntryDependency ) and is added to Compilation.entries .

(err, module) => {
  // ...
  const addModuleResult = this.addModule(module);
  module = addModuleResult.module;
  // for entry files
  this.entries.push(module);
  dependency.module = module;
  module.addReason(null, dependency);
  // start build stage
}

3. build

The build stage parses the source, runs loaders and generates the final source string. The main entry point is NormalModule.build , which delegates to doBuild .

build(options, compilation, resolver, fs, callback) {
  return this.doBuild(options, compilation, resolver, fs, err => {
    // parse source to AST
    const result = this.parser.parse(/* args */);
    if (result !== undefined) {
      handleParseResult(result);
    }
  });
}

Inside doBuild the loader chain is executed and the result is stored in this._source .

runLoaders({ resource: this.resource, loaders: this.loaders, context: loaderContext, readResource: fs.readFile.bind(fs) }, (err, result) => {
  this._source = this.createSource(this.binary ? asBuffer(source) : asString(source), resourceBuffer, sourceMap);
});

The parser converts the source (or an AST provided by a loader) into an AST using acorn , then walks the tree with the sequence program → detectStrictMode → prewalkStatements → walkStatements , creating dependency objects such as HarmonyImportSpecifierDependency , ConstDependency , etc.

4. Dependency processing

After the build finishes, Compilation.processModuleDependencies groups dependencies by their factory and resource identifier, filters out placeholder dependencies, and invokes the corresponding factories to create dependent modules. The recursion continues until the whole graph is built.

processModuleDependencies(module, callback) {
  const dependencies = new Map();
  const addDependency = dep => {
    const resourceIdent = dep.getResourceIdentifier();
    if (resourceIdent) {
      const factory = this.dependencyFactories.get(dep.constructor);
      // group by factory and identifier
    }
  };
  // walk through module.blocks, module.dependencies, etc.
}

Finally the compiled modules and their dependency information are used in the seal phase to generate chunks and the final bundle.

The article also includes diagrams illustrating each stage and a complete example with a.js and demo.js .

frontendWebpackJavaScriptbuild processDependencyModule
Didi Tech
Written by

Didi Tech

Official Didi technology account

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.