-
Notifications
You must be signed in to change notification settings - Fork 47
Conversation
|
Codecov Report
@@ Coverage Diff @@
## main #25 +/- ##
=======================================
Coverage 94.64% 94.64%
=======================================
Files 39 39
Lines 504 504
Branches 81 81
=======================================
Hits 477 477
Misses 27 27 Continue to review full report at Codecov.
|
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.
LGTM, good idea!
This could be quite a big problem. If the browser implementations are not used then there will be quite some things broken I would expect |
Having this should be very helpful for us in the Azure SDKs, as we use rollup to generate bundles for automated browser testing, and opentelemetry has historically been difficult to bundle (you can see an issue in rollup that's keeping us from migrating to newer bundles here: rollup/plugins#743, and opentelemetry triggers that bug). ESMs in the package should make bundling this package much more straightforward. @t2t2 please ping me if there's anything I can do to help test this or debug any of the potential improvements you've listed above. @richardpark-msft, @xirzec : JYFI |
@t2t2 Looks like the browser issue is fixed in a plugin rollup/rollup-plugin-node-resolve#8 Any way you can test real quick? |
@dyladan Yep did a bit more testing and turns out it was because I was missing browser option in the node-resolve plugin, all good with that |
It would be so lovely to get this in before the next release, I wish I had thought of it sooner! |
I'm concerned that this seems to completely duplicate the generated output, doubling the extracted size almost exactly.
This seems like an awfully high cost. Is there no way to generate files/output that is compatible with both commonJS and ESM? |
The main advantage, as I understand it, is that ESM customers can bundle/tree-shake what they need, rather than needing to dynamically import your package when distributing their app. And I don't believe there is any way to bridge the gulf between commonjs and ESM, since they have completely different syntax that can't be dynamically detected (i.e. |
IMHO, for only an additional ~160kB on disk (9kB on the wire), the benefits are very significant for browser consumers. This will be much friendlier for ESM-native bundlers that can decide to tree-shake the resulting code, hopefully resulting in smaller bundles and way simpler configuration at the expense of a slightly bigger package file. Ordinary CJS is usually not so bad for bundlers, but the transforms that TypeScript emits to support its syntactic features in ES5+CJS environments are difficult for bundlers like rollup to analyze statically. For example, if you look at the compiled output of this package, TypeScript emits an For what it's worth, for our Azure packages we ship both a CJS bundle (just a bundle of our code, no dependencies or anything other than our source) as the package "main" field as well as the ESM tree in the package "module" field. This seems like it offers a good balance of flexibility between bundling and using our packages with Node. |
Can we rename the package from |
@dyladan Makes sense, renamed it |
Why
While typescript uses ESM syntax, the code distributed on npm (build dir) has been transpiled to use commonjs require's for better compatibility. However this means that bundlers like webpack and rollup can't do tree shaking to remove code not imported by user, leaving behind unused dead code.
While
@opentelemetry/api
has lesser tree shake potential due to code with side effects, I figured the best way to tackle this is to first target the one package in it's own repo, and once good implementation is figured out copy it to packages in open-telemetry/opentelemetry-js and open-telemetry/opentelemetry-js-contrib.Relevant:
open-telemetry/opentelemetry-js#1378
open-telemetry/opentelemetry-js#1253
How about using type: module and exports? (as shown off by this tweet)
It's plausible but it may requires changes that might not be the best to do right before 1.0.0 release. Open this section for my attempt at it
While this will work instantly with rollup, there were issues with webpack and node.js. And well, second likely explains first. When package.json has type: module, node v12+ will also expect to see ESM code in *.js files and will use the file pointed exports map. There is however a difference - node.js requires file extensions when importing from files:
Similar error was also given by webpack, so it's probably just them copying nodejs behaviour
This can be fixed by adding .js to the end of imports in .ts files which seems odd as js files don't exist until built, but is the recommended way
There's also considerations needed for possible duplicated code loading when used by both esm and commonjs consumers and possible backwards compatibility breakage for imports from direct files (
import ... from '@opentelemetry/api/build/src/....
), so would rather not try to do all of this right now.How well does it work?
As noted above, due to side effects in index.ts it won't throw everything unneeded away but doing this over-simplified and totally unrealistic example:
mode: development
andoptimization.concatenateModules = true
(does tree shaking, is enabled with mode: production but I wanted to check human-readable output for signs of shaking)Potential improvements
(root)/lib
used for files generated from(root)/src
but keeping the current structure I leftbuild/src/
as-is and put esm version intobuild/lib/
Rollup seems to ignore file overrides in package.browserwas missing browser option in@rollup/plugin-node-resolve
, works as expected with that