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
Use ES2015 features in generated code snippets #4215
Conversation
Thank you for your contribution! ❤️You can try out this pull request locally by installing Rollup via npm install rollup/rollup#output-generated-code or load it into the REPL: |
Codecov Report
@@ Coverage Diff @@
## master #4215 +/- ##
==========================================
+ Coverage 98.37% 98.39% +0.01%
==========================================
Files 202 203 +1
Lines 7260 7341 +81
Branches 2119 2087 -32
==========================================
+ Hits 7142 7223 +81
Misses 58 58
Partials 60 60
Continue to review full report at Codecov.
|
627321f
to
9cccd75
Compare
For the SystemJS module format at least, it is recommended to retain a function declaration for the execute and declaration functions since SystemJS can control the If there is a slowdown for some specific "large IIFE" cases, it could also be worth sticking to function declarations there. I haven't been able to review all cases, as the diff is very hard to read on the web app, but also worth being very careful about |
But of course, eval is strongly discouraged to use in a bundling setup and we warn about it. Still, we could always use functions for With regard to other function replacement scenario, e.g. in dynamic imports, here arrow functions actually fix long-standing bugs with regard to wrong However, this PR finally adds a clunky workaround for the function case as well. |
To get a feeling for what changed, take a look at the new test files here, this should be far better than browsing the diff: https://github.com/rollup/rollup/tree/output-generated-code/test/form/samples/generated-code |
3388ebf
to
d6fe2ab
Compare
Not stepping in to discourage or anything of the sort; I ran into this twitter thread by the Preact author the other day and thought it was good food for thought while pursuing this initiative - https://twitter.com/_developit/status/1437429523893600256 |
I already reverted back to using ES5 syntax in the places where I am sure there would be a performance penalty. At this point, all remaining changes will provide either a small size reduction, or in the case of |
However, there are mailing important refactorings and quite a few bug fixes that are also included here. Most importantly, I managed to get rid of quite a few places where Rollup was NOT generating strict ES5 output. |
e819692
to
ef109d1
Compare
ce77c0e
to
5d9bcdf
Compare
This is finally ready for review! Have a look at the updated description, there are quite a few important fixes included as well. |
5d9bcdf
to
028d45e
Compare
028d45e
to
ae42302
Compare
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.
Excellent work, and glad to hear about the performance improvements.
I'd even consider making these features aggressive defaults - most users do want these features. Ideally a singular option for the target ecma version could apply across the board, for either enabling or disabling?
Glad to hear you approve! I added the preset style to make this as easy as possible, i.e.
I thought so originally, but there is still a large group of library bundlers who still think "es5" is what should go into node_modules. And many tools still assume that this is the case, forcing you to add exceptions to the config if you need anything in node_modules transpiled. But let's see what we make the default once Rollup 3 becomes more of a reality. |
This PR contains:
Are tests included?
Breaking Changes?
List any relevant issue numbers:
Resolves #3784
Resolves #3092
Resolves #2591
Description
This will finally support ES6 features like arrow functions in generated Rollup code. For now, this is completely opt-in, see below. Furthermore, this fixes some long-standing bugs and adds a new internal concepts of "code-snippets", small functions to generate parts of the code respecting the new options.
As it turns out, blindly switching to ES6 features is not always good idea, which is why most specifically, the
output.generatedCode.arrowFunctions
option will leave larger IIFE functions in place to avoid double parsing in Chrome (see the link in the documentation below for the reasoning). This is also linked to a hidden feature in this PRImproved AMD and SystemJS wrapper performance
Following https://v8.dev/blog/preparser#pife, immediately (directly or indirectly) invoked functions in AMD and SystemJS wrappers now receive the same treatment as their counterparts in UMD wrappers in that they are wrapped in parentheses. They are also never written as arrow functions as I could confirm that the same optimization does not apply to those.
Improved ES3 compatibility
While ES3 compatibility is generally not a goal of Rollup, we were already spending quite a bit of effort in quoting reserved words that are used as properties. This PR aims to complete this effort by quoting them in many more (all?) places that are controlled by Rollup. Props quoting can now be turned off via the
output.generatedCode. reservedNamesAsProps
option.For the next major version, I would consider defaulting this option to
true
.Improved ES5 compatibility + live-bindings for merged namespaces
Object.assign
is no longer used to merge namespaces. Instead, a custom helper function is injected, which not only improves compatibility but also retains live-bindings when internal and external or synthetic namespaces are reexported from the same file.Preserve "this"-context for AMD/CommonJS dynamic imports
Previously, dynamic imports containing a "this" in their argument would not preserve the context. This is fixed now in two ways:
Fix shimMissingExports for internally used exports
As it turns out, shimMissingExports would fail to add the definition for the shim variable even though it is referenced for internally used imports.
New feature (copied from documentation): output.generatedCode
To get a feeling for what has changed, take a look at the expected test output here: https://github.com/rollup/rollup/tree/output-generated-code/test/form/samples/generated-code
Type:
"es5" | "es2015" | { arrowFunctions?: boolean, constBindings?: boolean, objectShorthand?: boolean, preset?: "es5" | "es2015", reservedNamesAsProps?: boolean }
CLI:
--generatedCode <preset>
Default:
"es5"
Which language features Rollup can safely use in generated code. This will not transpile any user code but only change the code Rollup uses in wrappers and helpers. You may choose one of several presets:
"es5"
: Do not use ES2015+ features like arrow functions, but do not quote reserved names used as props."es2015"
: Use any JavaScript features up to ES2015.output.generatedCode.arrowFunctions
Type:
boolean
CLI:
--generatedCode.arrowFunctions
/--no-generatedCode.arrowFunctions
Default:
false
Whether to use arrow functions for auto-generated code snippets. Note that in certain places like module wrappers, Rollup will keep using regular functions wrapped in parentheses as in some JavaScript engines, these will provide noticeably better performance.
output.generatedCode.constBindings
Type:
boolean
CLI:
--generatedCode.constBindings
/--no-generatedCode.constBindings
Default:
false
This will use
const
instead ofvar
in certain places and helper functions. Depending on the engine, this can provide marginally better performance in optimized machine code. It will also allow Rollup to generate more efficient helpers due to block scoping.output.generatedCode.objectShorthand
Type:
boolean
CLI:
--generatedCode.objectShorthand
/--no-generatedCode.objectShorthand
Default:
false
Allows the use of shorthand notation in objects when the property name matches the value.
output.generatedCode.preset
Type:
"es5" | "es2015"
CLI:
--generatedCode <value>
Allows choosing one of the presets listed above while overriding some options.
output.generatedCode.reservedNamesAsProps
Type:
boolean
CLI:
--generatedCode.reservedNamesAsProps
/--no-generatedCode.reservedNamesAsProps
Default:
false
Determine whether reserved words like "default" can be used as prop names without using quotes.
(Soft-) deprecation of preferConst
output.generatedCode.constBIndings
should be used instead.Use common helper for more invalid option errors
An effect of this is that all invalid option errors now contain a link to the corresponding documentation.