Skip to content

Add library bundler#9489

Merged
devongovett merged 13 commits into
v2from
library-bundler
Mar 11, 2024
Merged

Add library bundler#9489
devongovett merged 13 commits into
v2from
library-bundler

Conversation

@devongovett

@devongovett devongovett commented Jan 14, 2024

Copy link
Copy Markdown
Member

Fixes #7254

This PR implements a separate bundler plugin for libraries that maps each input file to a separate output bundle, i.e. not bundling at all. This is desirable for libraries because bundlers handle separate files better for tree shaking (via the sideEffects field in package.json). It's especially helpful for component libraries that import CSS, because only the CSS for used components is included rather than everything.

This is currently implemented as a separate bundler plugin (@parcel/bundler-library) that you'd need to manually install and configure to use instead of the default bundler. Maybe this could be the default behavior in v3 though.

This is not fully complete (e.g. doesn't handle dynamic import in libraries which isn't too common), but it is able to successfully build React Spectrum.

}
resolved ||= potential[0];
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in this file are to handle the case where a dependency resolves to multiple bundles. In that case, we need to prioritize the one with the same type as the parent bundle. We also prioritize reference edges over bundle group resolution

})) {
this.externals.set(relativeBundlePath(this.bundle, b), new Map());
}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic ensures that we add imports for all referenced bundles. But we now wait to determine which symbols to import until they are used (below in addExternal). This way, we only include symbols user in this bundle instead of across all bundles.

This also switches to only including bundles non-recursively, otherwise we'd end up hoisting imports for things like CSS even if the library had "sideEffects": false. For a library, there's no need to hoist even with side effects. We leave that to the application bundler consuming the library.

Comment thread packages/packagers/js/src/ScopeHoistingPackager.js Outdated
} else {
return symbol;
return replacements?.get(symbol) || symbol;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check replacements in case a symbol got aliased to an external.

@devongovett devongovett changed the title WIP: Add library bundler Add library bundler Mar 5, 2024
@devongovett devongovett marked this pull request as ready for review March 5, 2024 01:29

if (
asset.meta.shouldWrap ||
this.isAsyncBundle ||

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be handled by the isAssetReferenced check below. The library bundler makes every bundle "async", but we don't want to wrap those.

Comment thread packages/core/integration-tests/test/output-formats.js
@devongovett

Copy link
Copy Markdown
Member Author

used the export {a as "foo-bar"} syntax for invalid identifiers (tc39/ecma262#2154). still not supported by typescript, but hopefully TS won't be parsing the JS in node_modules anyway. microsoft/TypeScript#49297

@devongovett devongovett requested a review from mischnic March 11, 2024 16:35
@devongovett

devongovett commented Mar 16, 2024

Copy link
Copy Markdown
Member Author

@mischnic ugh, looks like the string export syntax breaks webpack 4, which is still very widely used unfortunately. might need to revert that...

@mischnic

Copy link
Copy Markdown
Member

Looks like we don't have a choice...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Option to disable bundling for building libraries

2 participants