ClojureScript :js-provider :external with :target :esm — Undefined Peer Dependency Resolution Boundary
0 reputation · 17 Aug 2021, 00:04 UTC
0 reputation · 17 Aug 2021, 00:04 UTC
When targeting native ES modules with :js-provider :external, the ClojureScript compiler generates import statements for each top-level entry in :npm-deps but performs no analysis of the npm dependency graph beyond those keys. Transitive dependencies and peer dependencies declared by those packages are omitted from the generated import map, leaving resolution entirely to a downstream bundler.
The documentation does not specify whether dependencies, peerDependencies, or optionalDependencies from the resolved npm packages should be treated as required imports. A library that re-exports submodules (for example, react-redux re-exporting react internals) will produce import specifiers only for the declared :npm-deps key, not for the peer react dependency that must be present at runtime.
If an :npm-deps entry points to a package that lacks a valid ES module entry point (no exports field, no module field, only CommonJS), the compiler emits an import statement that will fail at bundle time without any compile-time warning.
What is the documented contract between the ClojureScript compiler and the external bundler regarding peer dependency resolution? Should the compiler analyze peerDependencies of declared :npm-deps and emit additional import specifiers, or is that explicitly out of scope? Is there a supported mechanism to declare required peer dependencies so the generated import map is complete?
:js-provider :external. The contract between the compiler and the downstream bundler is strictly one-level: the compiler maps the keys defined in your :npm-deps configuration to JavaScript import statements, delegating the entire dependency graph analysis to your final build tool (e.g., Vite, Webpack, or esbuild).
:target :esm, the compiler treats external dependencies as black-box modules. It does not inspect the package.json of your dependencies to check for peerDependencies, dependencies, or optionalDependencies. Consequently:
:npm-deps.node_modules algorithm."exports" field). The compiler will happily emit the import statement, causing a failure only when the bundler or browser encounters the code.:npm-deps map, even if it is technically a peerDependency of your primary library.resolve or Webpack's aliases) to ensure that peer dependencies are correctly mapped in the final bundle.package.json (at the root) includes all necessary peer dependencies so that npm install or yarn populates the environment for the bundler.In summary, the compiler's role is limited to translating Clojure symbols to specific JS imports. The responsibility for validating the dependency graph and resolving peer requirements lies entirely with the environment's build pipeline.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.