-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for ES Module and CommonJS output, and <script type="module"> #3545
Conversation
…dle group entries.
…to esmodule-output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the current design for includeNodeModules
is very useful, if you write a React library, you might want to bundle everything except react. If you develop a vscode plugin you want to bundle everything except vscode
(which is somehow injected dynamically at runtime) - I think aws
does something similar.
What usecases did you have in mind when chosing this syntax?
"outputFormat": "esModules", ❌
"outputFormat": "esmodules", ❌
"outputFormat": "esmodule",
🙈
Yeah this is the opposite usecase: when building a library you usually don't want to include any node_modules, but sometimes want to include one or two, for example, modules that are in the same monorepo. I have a repo which includes a bunch of react components that will be published as libraries, and I want to include the CSS along with it parts of which come from another package. We will eventually support a blacklist as well for externals, which are more useful when building applications. |
Co-Authored-By: Niklas Mischkulnig <[email protected]>
We can do this in a followup, but I found a case that could be better optimized: <script src="./main.js"></script> import("./lib.js").then(v => {
console.log(v);
}); Browserslist: Chrome 70 (so dynamic import is supported) |
Oh |
Yes! |
import path from 'path'; | ||
import nullthrows from 'nullthrows'; | ||
|
||
export function relativeBundlePath(from: Bundle, to: Bundle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really an URL rather than a path (because it returns a URL with forward slashes also on Windows).
Tip: use "Close T-74" or "Fix T-74" next time. |
Awesome, had no idea. Gonna leave that as a followup task. |
This pull request has been linked to 1 task:
|
Related: #3011 #1168.
This is a refactor of the scope hoisting compiler to support multiple module output formats, including ES modules, CommonJS, and browser script output. This allows much improved support for building libraries with Parcel, and also enables native browser ES module output with
<script type="module">
. 🎉The babel transformer has been adjusted to take ES module targets into account when building, and automatically use a higher browser target for ES module supporting browsers when that target is seen. Also our loader infrastructure will automatically include an
import()
polyfill when needed, as not all esmodule supporting browsers support dynamic imports. But, if you only target dynamic import supporting browsers, then the polyfill is not included. Without any loader runtime code or prelude, bundle sizes should be significantly smaller with native esmodules.In addition, the behavior of the TargetResolver has been changed to treat the package.json
main
,module
, andbrowser
fields as library targets rather than app targets. This means that you will get CommonJS or ES Module output by default with those fields instead of browser script output. Also, loaders for async resources (e.g. css) will be excluded and native imports will be left in place instead, which can be picked up by another bundler later.This required introducing two new fields to the
Environment
object:outputFormat
, andisLibrary
. The TargetResolver sets these fields automatically based on package.json information, but they can also be configured manually. In addition,outputFormat
is automatically set toesmodule
by the HTML transformer when a<script type="module">
tag is seen, and turned off when<script nomodule>
is seen. This makes it really easy to create multiple targets if you use an HTML entry point.Limitations: these new output formats are only supported with scope hoisting enabled, so won't work in development mode. Features like HMR just aren't possible with ES modules, and we also don't currently track enough import/export metadata without the scope hoisting compiler. This is probably fine though as this is meant as an optimization, and will result in faster compilation during development (only need to compile the
nomodule
version).Other changes:
includeNodeModules
flag now supports taking either a boolean or a whitelist of module names to include for more granular control.includeNodeModules
is now processed by the resolver instead of in the transformer. A dependency is always created now, but sometimes isn't resolved to anything. This allows us to keep the metadata about what symbols were imported etc., but not cause any transforming to occur. AnisExcluded
flag can be set by the resolver to cause the ResolverRunner to returnnull
instead of throwing an error.useBuiltins: 'usage'
option has been reverted touseBuiltins: 'entry'
. Usage is far too aggressive about including polyfills, and seemed to result in much larger bundle sizes unnecessarily. If you need polyfills, you can include them yourself.Future work:
module
/nomodule
automatically