TypeScript became a standard for backend (Node.js) and frontend (Angular/React) development. The types it brings indulge us to develop apps with the conviction that we won’t make any silly mistakes. It doesn’t relieve us from the responsibility of using weightier coding practices, but it does make developers’ lives a bit easier. Yet there is one downside of TS. It’s compile time. So, let’s talk well-nigh how to speed up your TypeScript project.
The increasingly lawmaking you have, the longer it takes to compile. I think we can all stipulate on that. In some cases, that’s moreover the reason why we split the using into smaller pieces (services), so we don’t need to compile everything.
Let’s take our Express Boilerplate (the starter we’re using to build apps for our clients). To speed up the minutiae process, we’ve built a starter pack that reflects our way-to-go stack.
- production-ready containerization,
- TypeScript support,
- Plop for lawmaking generation,
- built-in support for Redis and PostgreSQL with TypeORM,
- best practices like Writ pattern or Dependency Injection with Awilix
- REST/graphQL API support,
In its raw form, running the `npm run watch` writ (which starts the TypeScript Compiler – tsc – in a watch mode) takes 28 seconds to have an environment ready to work with.
It doesn’t sound like a lot, but with increasingly lawmaking to come, this number will slowly increase. So what happens during compilation?
In short, there are two major components:
- types checking,
At this point we cannot do much with the first one, however, there is a way to speed up the transpilation part.
TypeScript itself can’t transpiration TS lawmaking into JS files. There is no such functionality. However, there is one that allows us to trammels types only – –noEmit flag.
So what if we use something faster for a transpilation part and use TSC only for TS types checking?
What is SWC?
Our Boilerplate compiles in 7 seconds. That’s 4 times faster than using the seated TypeScript tools. So how does it work?
SWC can be installed as standard devDependency with:
npm i -D @swc/core @swc/cli
And that’s all! At least for some vital features. 🙂
You can try it by running:
swc <some-directory> --out-dir build
and in a second you should get the lawmaking transpiled. If you need to have a watch mode, then just add the -w flag at the end.
Of course, it is a little bit increasingly complicated for increasingly ramified projects. By default SWC has most of the features turned off and for many TypeScript applications, it will be necessary to add spare configuration.
This could be washed-up with a special .swcrc file.
Sadly there is no tool that creates swc configuration from tsconfig yet. Therefore, you should remember to alimony both files in sync.
There are a few useful keys in the SWC config.
The first one is jsc. This key contains everything related to the parser type we’re going to use – for example typescript or ECMAScript, but moreover some information well-nigh the target js version we want our lawmaking to be converted to.
The second one is a module. This one is expressly useful for Node.js apps, considering of the CommonJS modules requirement.
For most of our apps, we moreover had to turn on the decorators support, otherwise you’ll get a nasty error message.
Obviously, those are only a few of the many possible configuration options. Feel self-ruling to trammels the remaining ones on the SWC configuration website.
What well-nigh types?
One question remains unanswered. Do we waif types checking? In fact, SWC doesn’t superintendency well-nigh the lawmaking validity nor it cares well-nigh types. So in reality we’re losing the biggest reason to use TypeScript for. What the hell?! Don’t worry we are not doing that. 😊
At the whence of this article, I mentioned that TS can work in two ways. It either generates the lawmaking and checks types or only checks types. Let’s use the second tideway then!
The writ we need is simple:
tsc -w --pretty --skipLibCheck --noEmit
Yet we still need to run both in parallel – SWC and TSC. We can either use a library for that (to have cross-operating system functionality) or we can just use and run both simultaneously.
swc src --out-dir build/src -w --sync & tsc -w --pretty --skipLibCheck --noEmit
What is the goody of that approach?
The app is ready to develop in 7s, and at the same time, we’re going to get all of the information well-nigh possible errors in our code.
The larger our app gets, the worthier the difference between SWC and TSC is going to be, so having the possibility to develop older is a huge advantage.
So where is the catch? – you may ask.
The lawmaking generated with SWC is a little bit variegated from the one generated by TSC. In some cases, this leads us to some issues with our tsc-working application.
For example, depending on a configuration, decorated classes are returned as classes or objects (yet in tsc it is unchangingly going to be a class). It doesn’t sound bad, but if any of your functions requires the explicit type (for example class), it will break. We had this problem with the Awilix helper asClass.The other problem is the support of new features. SWC is evolving pretty quickly, yet it still doesn’t support all of the features that TSC/Babel does. The most up-to-date list of features is misogynist on the SWC website. But it is moreover worth checking the GitHub issues pages.
So would I recommend using SWC?
There is a unexceptionable side here. It is very easy to switch when and along between SWC and TSC, so we all should requite it a try. At The Software House we’re going to play with this a little bit increasingly to see how stable it is in larger projects. However, at this point I’m very happy with the results!
Do you want to build faster with TypeScript? This is just one of many questions you need to wordplay for your next project.
Contact The Software House and tackle them all. Initial consultations are self-ruling of charge!