Skip to main content

19 posts tagged with "ts-loader"

The TypeScript loader for webpack.

View All Tags

Migrating ts-loader to TypeScript 7.1 with AI

· 10 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

TypeScript is now the most popular programming language. Incredible. I was an early adopter back in 2012 and have since worked on a number of open source projects in the TypeScript ecosystem.

One of them is ts-loader, which integrates TypeScript the language with webpack; which is used to build web applications. You might be surprised to know ts-loader has 54 million downloads a month. I know I am. I'll be honest - I'm using Vite far more than I use webpack these days, but there are still a lot of people using webpack and ts-loader. And I intend to continue to support them.

Just lately, TypeScript was ported from being written in TypeScript to being written in Go. The reason being for performance - make TypeScript tooling 10x faster. TypeScript 7 is written in Go.

This has implications for ts-loader as it is built on APIs the TypeScript library exposed. But those APIs were not ported to TypeScript 7. New ones are being written, recently I heard that the first emit APIs had landed in the nightly version of TypeScript.

Porting with AI

I would like ts-loader to be able to support TypeScript 7.1 when it comes. This will be the first Go built version of TypeScript which ships with an API. But I'm quite lazy and I have / had very little interest in doing the migration manually.

Instead I intended to use my GitHub Copilot and Claude licenses. What follows is a diary of the port. The things I did, what was useful / wasn't, the principles followed etc.

In fact, let's start there: principles:

  1. I wanted AI to do most of the work
  2. I reserved the right to not port all features The codebase of ts-loader is more than 10 years old, and I was pretty sure we didn't need everything that we'd accreted over the years.
  3. I still intended to support webpack 4 and 5 unless there was a compelling reason not to.
  4. The minimum supported Node version for ts-loader right now is 12. That has long been end-of-life and so it feels appropriate to bump the minimum supported version of Node to something higher; probably 22.

The initial port

I thought I'd start off by firing this prompt at GitHub Copilot to get it to do some analysis and put that on an existing issue that discussed TypeScript 7:

Screenshot of initial port prompt which reads "following the addition of the emit API in this pull request: https://github.com/microsoft/typescript-go/pull/4699 please determine what this potentially means for ts-loader See context here: https://github.com/TypeStrong/ts-loader/issues/1671#issuecomment-4937039062 Please add a comment to that PR with your findings"

It did some decent analysis and claimed it had added the analysis to the issue. It had not:

Screenshot of me telling GitHub Copilot it had not added a comment

It told me it had added the comment again, and it had not. So I challenged it once more.

Screenshot of me telling GitHub Copilot it had not added a comment again

And then it happened again, so I tried sarcasm.

Screenshot of me telling GitHub Copilot it had not added a comment again sarcastically

At this point I realised I was getting distracted.

The analysis was decent and so I asked it to PR it, which it did. One thing I have generally learned about AI is that it loves backwards compatibility. And this PR was that shaped; it was looking to support both the old and new APIs. This seemed complicated. After some fiddling and thinking, I figured I'd rather just support the new API and drop support for the old one.

Dropping support for the old API

So I asked it to go again, but this time to drop support for the old API:

Screenshot of second prompt which reads "https://github.com/TypeStrong/ts-loader/pull/1703 is a good first attempt at implementing the new tsgo API support but is too complicated because it maintains existing support as well. Please try implementing new API support alone instead. Drop existing support. We would like execution-tests to pass - comparison-tests need not pass initially. Use npm@7.1.0-dev.20260725.1 or newer for implementing. See https://github.com/microsoft/typescript-go/pull/4699 for additional context."

The PR it came up with was decent: https://github.com/TypeStrong/ts-loader/pull/1704 - this became the basis for the port.

A little bit of context; ts-loader has two test packs. The comparison test pack are tests that compare the output of ts-loader with known outputs; they're effectively snapshot tests. The execution test pack are tests that run the output of ts-loader and check that it behaves as expected. The execution tests are more reliable than the comparison tests and can be run against multiple versions of webpack and TypeScript. The comparison tests are only run against a single version of webpack / TypeScript, and are somewhat brittle. But they're useful for checking error states.

With minimal assistance from me, it got the execution tests passing. This was an awesome start.

Getting the comparison tests passing

At this point I had a version of ts-loader that supported TypeScript 7.1. But the comparison tests were failing. It was also at this point that my GitHub Copilot tokens ran out; so I switched to using Claude.

From here on out my workflow became pretty simple. I would point Claude at a failing comparison test, and ask it to fix it:

screenshot of a terminal that reads "please fix yarn comparison-tests --single-test basic"

A lesson I learned early on, was to start with the simpler tests and work up to the more complex ones. I'd initially not used that approach and found that Claude was "fixing" the more complex tests in a way that broke other ones. So I started with the simpler tests and worked my way up.

As I was doing this I also decided to drop some functionality that had existing in ts-loader for a while. For instance, Happypack is archived and no longer maintained. So I decided to drop support for it in ts-loader.

Giving Claude a Windows avatar in GitHub Actions

In a couple of days of fiddling in my spare time, we got to the point of fully passing execution tests and comparison tests. However, they were only passing on Linux and Mac. The Windows tests were failing. I do have access to Windows machines, but my boys have hijacked them for gaming. So I pondered if Claude could somehow make use of Windows machines running in GitHub Actions.

The answer was yes. If it had access to the GitHub CLI and we created a GitHub Actions workflow that ran on Windows, it could use the CLI to run commands on the Windows runner. So we created a workflow that ran on Windows: https://github.com/TypeStrong/ts-loader/pull/1705

With that in place, Claude was able to run the comparison tests on Windows and fix the issues. It was a bit of a slow process, but it worked. After some time, we got to the point where all tests were passing on all platforms. This made me very happy!

Also, the boys were pleased as I didn't have to use their machines for testing. I say "their machines" - technically these are my laptops that they borrowed and never gave back. But I digress.

Goodbye chalk, hello picocolors

One of the benefits of moving to Node 22 as a minimum is that we can use the built-in styleText API instead of the chalk library. There's lovely documentation on how to do that here: https://e18e.dev/docs/replacements/chalk.html#styletext-native and it was my initial plan to use it.

However, there was some odd behaviour which meant that output differed between platforms. After trying to work around that and deciding it was too complex, we switched to using picocolors instead. This still reduces the dependency weight of ts-loader and it makes ts-loader faster. It's a win-win.

Goodbye typescript-eslint, hello oxlint-tsgolint

At the moment ts-loader uses typescript-eslint to lint the code. However, that library is not compatible with TypeScript 7.1. So we have switched to using oxlint-tsgolint, which is a new linter that supports TypeScript 7.1. It is also faster than typescript-eslint. You can read more about it here: https://oxc.rs/blog/2026-07-22-type-aware-linting-stable

I feel slightly torn on this one as I've long used and liked typescript-eslint. I may return to it when it becomes compatible, but I couldn't take seeing the red cross in the GitHub Actions workflow for ts-loader any longer.

What is still to come?

Around this time I got excited and posted on Bluesky about the progress. Andrew Branch, one of the TypeScript team members that has worked on the API, replied to my post:

screenshot of Andrew Branch's post on Bluesky saying "Awesome! FYI, transpileModule is coming soon too"

This was a good reminder that what we had done was not the end of the story. If you're a ts-loader user then you might be familiar with the transpileOnly option. This allows you to transpile TypeScript code without type checking. The port as it stands does not properly support this option as the APIs aren't yet there. When they land, we'll look again.

There's also other features that are not yet supported. For instance, custom transformers and project references. If / when APIs appear for these, we'll look to support them in ts-loader.

How good is the code?

It's not too bad. I've deliberately not looked too hard at it as yet. It made a few peculiar choices that I have addressed, but overall it is pretty good. I'm planning to have a proper look at it further down the line.

One surprising thing is that it has added a lot of comments to the code.

screenshot of code with a lot of comments

I don't like it. However, for now I'm leaving the comments in place, on the assumption that it helps Claude understand the code better. I will remove them before we merge.

When do we ship?

Well, not before the API has been released, which is likely to be later this year. But when it is, we will ship a new version of ts-loader that supports TypeScript 7.1. It's probably going to be v10 of ts-loader, so we can drop support for the old TypeScript API, Node 12, Happypack etc.

For now, if you want to try out the port, the pull request is up and can be found here: https://github.com/TypeStrong/ts-loader/pull/1704

Open source: Who is your DR?

· 4 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

It's been a rough year. In March I was diagnosed with a serious illness. I've written about my diagnosis on my personal blog and I won't repeat what I said there here. But the TL;DR is this: I was told that without treatment things looked bleak. Happily, there was a follow up sentence; there is treatment and I am now having it. Whilst nothing is guaranteed, the doctors have used phrases like "cautious optimism". Time will tell what happens, but I am hopeful that I will be around for a while yet.

However, this has made me think about the future of the open source projects I maintain. If I cannot maintain them anymore, what happens? That's what the title of this blog post means; what, or who, is the DR (that's Disaster Recovery not Daniel Rosenwasser) for my open source projects? Maybe there's a better term than "Disaster Recovery". Having worked on various systems over the years, I've often been involved in disaster recovery planning for them. It always comes down to answering this question: what takes over when everything goes wrong?

title image that reads "Open source: Who is your DR?"

ts-loader goes webpack 4... again!

· 6 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

Back in 2021 I published a post called ts-loader goes webpack 5; a big exciting post about how ts-loader was upgraded to directly support webpack 5, and drop support for webpack 4 in v9 of ts-loader.

For reasons which I'll get into shortly, as of v9.6.0, ts-loader now supports both webpack 5 (as it did already) and webpack 4. So if you're a webpack 4 user, you can now use ts-loader@9, rather than using ts-loader@8.

title image that reads "ts-loader goes webpack 4... again!" with TypeScript and webpack logos

ts-loader goes webpack 5

· 8 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

ts-loader has just released v9.0.0. This post goes through what this release is all about, and what it took to ship this version. For intrigue, it includes a brief scamper into my mental health along the way. Some upgrades go smoothly - this one had some hiccups. But we'll get into that.

hello world bicep

ts-loader 2017 retrospective

· 5 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

2017 is drawing to a close, and it's been a big, big year in webpack-land. It's been a big year for ts-loader too. At the start of the year v1.3.3 was the latest version available, officially supporting webpack 1. (Old school!) We end the year with ts-loader sitting pretty at v3.2.0 and supporting webpack 2 and 3.

Working with Extrahop on webpack and ts-loader

· One min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

I'm quite proud of this: https://www.extrahop.com/company/blog/2017/extrahop-webpack-accelerating-build-times/

If you didn't know, I spend a good amount of my spare time hacking on open source software. You may not know what that is. I would describe OSS as software made with ❤ by people, for other people to use.

You are currently reading this on a platform that was built using OSS. It's all around you, every day. It's on your phone, on your computer, on your TV. It's everywhere.

It's my hobby, it's part of my work. This specifically was one of those tremendously rare occasions when I got paid directly to work on my hobby, with people much brighter than me. It was brilliant. I loved it; it was a privilege.

Here's to Open Source!

Under the Duck: An Afternoon in Open Source

· 6 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

Have you ever wondered what happens behind the scenes of open source projects? One that I'm involved with is ts-loader; a TypeScript loader for webpack. Yesterday was an interesting day in the life of ts-loader and webpack; things unexpectedly broke. Oh and don't worry, they're fixed now.

Using ts-loader with webpack 2

· 8 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

Hands up, despite being one of the maintainers of ts-loader (a TypeScript loader for webpack) I have not been tracking webpack v2. My reasons? Well, I'm keen on cutting edge but bleeding edge is often not a ton of fun as dealing with regularly breaking changes is frustrating. I'm generally happy to wait for things to settle down a bit before leaping aboard. However, webpack 2 RC'd last week and so it's time to take a look!

But you can't die... I love you!

· 6 min read
John Reilly
OSS Engineer - TypeScript, Azure, React, Node.js, .NET

That's how I was feeling on the morning of October 6th 2016. I'd been feeling that way for some time. The target of my concern? ts-loader. ts-loader is a loader for webpack; the module bundler. ts-loader allows you use TypeScript with webpack. I'd been a merry user of it for at least a year or so. But, at that point, all was not well in the land of ts-loader. Come with me and I'll tell you a story...

a poster that reads: "But you can't die... I love you!"