206 karma · joined November 2, 2016
You're spot on with all of your points. The isolated declarations feature forces your code to be written in a way that creating the .d.ts files is a mere exercise of stripping syntax and can be done easily without invoking the tsc compiler.
For runtimes like Deno which support running TS natively (disclaimer: I work for Deno) you never had to care about creating .d.ts files when publishing your package to any of the Deno registries: previously /x, now JSR. In the background though we've always tried to feed the tsc compiler in Deno something like .d.ts files though as it's quicker for type checking purposes.
I mainly work with Deno which can run TS files natively (disclaimer: I'm employed by them). This changes the parameters a little as all registries for Deno could always ships the TS sources directly. But when publishing to npm you always have to publish the JS sources to work with runtimes like Node that don't support running TS natively.
In Deno (disclaimer: I work for Deno), which supports running TS natively, packaging outside of npm has always worked by shipping the TS files directly. Transpiling them down to JS files is only something you ever had to do when publishing on npm.
So far the problem that a dependency only compiles with a certain version of tsc hasn't popped up since Deno was launched. But that may have been because Deno always ships with latest TS and Deno users don't hesitate to update as we haven't done any breaking changes so far.
Happy to hear that you like the series!
There are cases where folks write them by hand, but that's not what I had in mind when writing the article. I've rephrased that part a bit to hopefully make it less confusing.
For Node users the isolated declaration feature won't do much other than speed up the creation of the .d.ts files a little. For runtimes that can run TS natively like Deno (disclaimer: I work for Deno) the benefit is much more apparent as you always want the original TS sources, but can generate .d.ts files on the fly for faster type checking.
EDIT: Formatting
That's exactly what JSR does. We generate the package.json ourselves.
By ensuring explicit return types in the public API, the generation of .d.ts files is turned into a mere syntax transform, rather than requiring the tsc compiler. This is something TypeScript will ship with in the next release itself. They're adding a new `isolatedDeclarations` option which is the same thing.
JSR is a registry, not a package manager. npm allows you to add multiple registries and JSR provides an npm API endpoint. From npm's point of view packages coming from JSR are the same as those coming from the npm registry itself. The only difference is where the package is coming from, but all semver resolution, etc are done as usual by whatever package manager you use.
Disclaimer: I wrote a good portion of the npm tarball generation code.
https://github.com/jestjs/jest/blob/00ef0ed0a03764f24ff568bc...
Compilation isn't the problem, loading and instantiating the module graph is. The timings for that are currently not exposed in any runtime afaik.
That's fair criticism. Whilst the setup shown in the article is synthetic, the experience is from working on real world projects. I've worked on a bunch of projects which had about 3000-6000 barrel files easily, and these then lead to every file in the project always being included. The total amount of files being loaded was somewhat around 30-60k, depending on the project.
I did the exact same thing as described in the article and wrote a custom test runner for jest that bundled the test files with esbuild before executing them. Even though bundling introduces a costly overhead on its own, it was still about 60% faster to bundle + run the bundled code vs not doing it. Bundling can also be amortized because it only needs to be done once per test run vs once per file. That's where the real gains came from, because in jest every single test file constructs the whole module graph from scratch.
I haven't checked myself, but there is likely improvements to be made in node (or other runtimes) to address this. Hopefully, some folks get inspired by this article to look at that.
Deno encourages you to submit the original sources which can be even in TypeScript if you want. The users are very close to the newest Deno release and there is barely anyone staying on old versions. This works because Deno takes semver very seriously, which in turn encourages folks to upgrade. It removes the need for polyfills and allows you to always use the latest JS features.
Disclaimer: I work at Deno
I wish we as in the industry would find a better solution to adapt to this. It's a bit unfortunate that the polyfills as part of the library code itself, which makes it difficult to get rid of them once they're not needed anymore.
Thanks for the kind words! It's feedback like this that encourages me to keep writing about it.
I share your experiences regarding babel helpers and haven't found a good solution myself. Similar to you, I often patch unnecessary stuff out via patch-package, but that approach doesn't scale well.
Good point. Agree that the ideal scenario would be that the end user (or the tools they use) have the final say in which polyfills to load. It's a bit of a bummer that they are shipped as part of npm packages without an easy way to get rid of them.
I wonder if our industry will move to publishing the original source files to npm in the long run. Only the last piece of the chain, the developer using these dependencies, knows what their target environments are. So the bundler could then downlevel or polyfill the code for the specified targets.
That mirrors my experience too on working in various projects. The automatic polyfilling story is such a good thing in theory, but reality isn't as rosy and much more polyfills than necessary are included.
Thanks for the kind words! I'm in the same boat as you, profiling is a lot of fun! Yeah, the more you look, the more you realize how many projects have the same or similar problems. Hoping that more folks are aware of those issues and how to avoid them with this series.
We decided to open the PR nonetheless as people kept asking us about it: https://github.com/estools/esquery/pull/134
That's great feedback! After reading your comment and re-reading the section in the article it does indeed sound wrong. Decided to remove that paragraph. Your explanation of the string representation is really good. Thanks for sharing!