What this final step is going to do is to take all of those explicitly TS dotted names and make them named imports. So this is much, much closer to what we actually want at the end of the day. And in fact, if you took the code and you diffed it against the original state of the world, the only thing that would have changed is the import line itself. The code below is identical.
And at this point, the tedious work is done. But we're not done yet, because there's loads of manual changes that we have to make after the bulk transformation. In fact, there were 29 commits. Obviously, this is kind of scary, right? Because any of the changes upstream could break any of our patches, and we're going to have a bad time. But thankfully, we were using Git to manage these. So when we go to ask Git, hey, apply all these patches, it's going to go, hey, your patch didn't apply, can you fix the problem? And then we continue the rebase. And then we just ask it to dump the patches. The patches are stored with the transformation tool, so when the time comes, we can just run the tool and it works.
Now, obviously there are 29 manual changes, so I can't go through all of them. But there are some really interesting ones. So first of all, we're bundling TypeScript using ESBuild. For various reasons, TypeScript still wanted to ship all of its code as these large bundled files. Before, we saw that it was produced by outfile and prepend, so if we want to recreate those same files in new TypeScript with modules, we need to use some sort of bundler. There's lots of bundlers out there, I won't try to list them all, but I went with ESBuild. Obviously, it's really, really fast, so 200 milliseconds to build TSC is really good. It also has a lot of really great features, such as scope hoisting, so that's taking all the code out of people's modules and pulling them to the top level so you don't have to indirect. There's tree shaking, so removing dead code, and then enum inlining. So, when we declare our enums in our compiler, they get inlined and thrown all over the code so that it's faster and doesn't have to go through an object lookup.
Now, obviously, we're depending on an external project to bundle our code, and just to make sure that we can still run ourselves in work, our build has an alternate mode called nobundle, and just make sure that we can emit all of our code as common.js and it continues to function. Now, because we're using esbuild to bundle, there's no one around that can bundle the DTS files. So, I ended up rolling up my own DTS bundler. It's about 400 lines of code. There are many other DTS bundlers out there, API extractor, TS up, rollup plugins, etc. And they all are good in their own way, but for us, we only needed a very small subset of the features. Specifically, because we were using namespaces, we didn't have any naming conflicts. And so, we were able to use our own custom bundler to go a little bit faster, but also produce an output that looks a lot like our old output.
Comments