[BREAKING/v3] Exclude node builtins from build#1604
Conversation
🦋 Changeset detectedLatest commit: 327118a The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
You can use Might be neater to construct this from that list rather than hard code it directly, this future proofs any new modules added in later node versions. |
Yeah, that makes sense. I was a bit nervous using an unofficial list that someone has to update and is one level away from us, but it seems half on the Internet rests on Sindre's shoulders anyway :) |
e01a1e1 to
327118a
Compare
TL;DR: exclude node builtins from build to make packages that import them but don't use them at runtime work. Works in esbuild mode and webpack mode, althought slightly differently.
Webpack v5 has stopped providing polyfills for imported Node builtins, as it's considered bad practice to import a "node" package in a "browser" app. Create React App is similarly opinionated, and doesn't provide any polyfill or fallback. I think modular should follow this opinion, unless we get overwhelming feedback indicating the contrary.
The problem is that some third party packages that provide both browser and node implementation don't distribute it into different files (there's a mechanism to do that, but it's not widely used yet), but they expose a single file that initially
require()s everything (built-in modules included) and decides what to use at runtime, based - I guess - on capability sniffing (require(builtin); if (isNode) { useBuiltin() } else { useBrowseEquivalent() }). These modules, that would normally work without polyfills, now break the build. This happens, for example, withsolclientjsanddotenv.This PR adds
fallback: falsefor all the node builtins required in the build, so that they get a non-meaningful value at runtime. If they're never used, that won't make a difference, but they won't break the build. This is breaking in respect to what modular v2 does (-> modular v2 uses webpack 4 that automatically provides polyfills)This PR also externalises all node builtins in esbuild mode. This is analogous to what we do in Webpack mode, with the difference that if there is an npm module with the same name as a npm builtin in the extended dependencies, it will be excluded from the build (while webpack will use the homonym npm module instead). npm packages that are homonym to builtin packages are a legacy residue and are mainly deprecated, but if they're used by any third party library, they won't work in esbuild mode. I don't know a way to provide a fallback behaviour similar to webpack with esbuild. This is breaking in respect to what modular v2 in esbuild mode does (-> modular v2 always breaks when there is a builtin package in the build)