Challenge 2: Why CommonJS's Graph Can't Be Reliably Parsed Statically — Possible Solution ==================================================================== THE DYNAMIC-REQUIRE EXAMPLE ------------------------------ Per this chapter's own example: if (useMetric) { const converter = require('./metric.js'); } The require() call here is wrapped inside an ordinary JavaScript if statement. Whether this line ever actually executes — and therefore whether './metric.js' is really a dependency of this file at all — depends entirely on the runtime value of useMetric, a value that might come from user input, a config file, or any other source not knowable just by reading the source code. WHY A BUNDLER CAN'T RELIABLY DETERMINE THIS BY PARSING ALONE ------------------------------ To know for certain whether './metric.js' belongs in the dependency graph, a tool would need to know whether useMetric is ever true — and that's a question about the program's RUNTIME BEHAVIOR, not something derivable purely from the text of the file. In general, determining whether an arbitrary conditional will ever be true is not something static parsing can solve reliably (the condition could depend on values only known once the program actually runs). Per this chapter's own comparison table, this is exactly why CommonJS's "full graph knowable without running the code" answer is "not reliably," while ESM's is "yes, always" — ESM's import statements have no such conditional escape hatch to begin with. WHY THIS DETERMINES WHETHER TREE-SHAKING IS SAFE ------------------------------ Per this chapter's own explanation, tree-shaking works by removing any part of the dependency graph the entry point doesn't actually reach. If a tool can't be CERTAIN whether a given require() call will ever execute, it can't safely conclude that the file it references is truly unused — removing it based on an incomplete, static-only analysis risks deleting code a real (but conditionally-triggered) code path genuinely needs at runtime. ESM's static-only import structure avoids this risk entirely, because there's no conditional path that could hide a real dependency from static analysis in the first place — which is exactly why tree-shaking is described as reliable for ESM but not for CommonJS. WHY THIS WORKS AS AN ANSWER ------------------------------ It explains specifically why the conditional require() call makes the dependency genuinely uncertain without running the program, and connects that uncertainty directly to why tree-shaking safety depends on it — an analysis tool can't safely remove something it can't be sure is actually unused.