Lesson Description

The "Project References & Configuration" Lesson is part of the full, Enterprise UI Development: Microfrontends, Testing, & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve explains how to manage TypeScript configurations in a monorepo by using a base tsconfig file extended by smaller slices for different parts of a project. He highlights the benefits of breaking the project into smaller pieces for incremental builds and type sharing without publishing to npm. He also discusses targeting specific runtimes and customizing configurations for different application slices, such as Chrome extension components, to optimize build and type checking processes.

Preview

Transcript from the "Project References & Configuration" Lesson

[00:00:00]
>> Steve Kinney: For the purposes of we're wearing a monorepo or something along those lines, we might reference the references or the other, in this very clearly because this is based on the repo we were working with all day yesterday, which is this idea that you can say, here are the other packages that we're working with, right? And in the same way, if you've ever done a thing where it's like you hold command and click in VS Code and it jumps you into that type definition in the node modules folder, right, now you're kind of getting a version of that across the different slices of your monorepo or what have you, right?

[00:00:39]
So it kind of understands what's part of this project, what are in these other things, so on and so forth. Robert's solution of collapsing down some of the files is useful. Composite means this is one piece of a larger project. The incremental means try to cache stuff as we went through, so on and so forth. And a pattern you'll see a lot is, you know, maybe at the root of the directory, you might see like a tsconfig.base.json, right?

[00:01:14]
This is very similar to when we saw the catalogs with PNPM workspaces, right? Where, hey, here's going to be the shared configuration, right? We're all going to target, because eventually, if you're doing the thing of a build time situation, you are targeting one runtime, right? You're either, you know, targeting, depending on what your company you support in terms of browsers, right, or if you're targeting Node or what have you, right?

[00:01:46]
And so these are the things you're kind of sharing across all of them, and then in your individual packages, you're saying extends, and yes, you have to do the dot dots here, sorry, I don't make the rules. But now at the top of the repo, we have the base, you know, tsconfig.base.json, and then each smaller slice is extending that with, okay, and a lot of times I might not have anything in compiler options, but I was working on this one project a few months ago, I think I mentioned this yesterday, it was a Chrome extension where the types that I needed for each kind of slice of the application were different, right?

[00:02:27]
Service workers don't have access to the DOM, they have access to worker-like APIs, they had full access to the Chrome API. The content script, which is what runs in the browser, has access to only two pieces of the Chrome API, but it has the DOM, and then the side panel has both the entire DOM and the entire Chrome API, right? And so I needed at least three tsconfig files, but I could basically say, and I was targeting a modern Chrome, so in the base was like, we're targeting ES, I think I was doing ES Next, but whatever, ES 2022, it'll change.

[00:03:07]
And then for each one I could say what libraries or what things we include, like whether or not this one supports JSX, so on and so forth, right? You can extend that base config, and so you're kind of keeping the parts that matter shared across the entire set of teams, and then for your particular slice of it, you know, if you need to have, you know, what files you want to include or exclude, so on and so forth, right?

[00:03:35]
Like, you know, you might have a thing where there are some JSON files that you're only displaying and you don't want them part of the type check, so on and so forth. You can add those to exclude and figure that out as you go. And yeah, then you can also pull in the references of what are the other, you know, if you are then depending on the shared package of the UI package, saying we're also going to pull in that and we'll pull in its tsconfig file, those will be built incrementally, right?

[00:04:06]
And so you start to just break it apart into smaller pieces so that TypeScript does not start losing its mind. And then the other thing to do is, and this is now for package.json, since you have Turborepo, and Turborepo could build the assets, like if you're using Vite to pull everything in, or using Bun or something that can read TypeScript files, you don't necessarily need to build everything, right?

[00:04:33]
But if it's like, hey, the host application is running regular JavaScript or something along those lines, or for instance, when I was working on the Chrome extension, those need to be JavaScript at the end of the day, or if you use SvelteKit, the plugins that you pull into a SvelteKit configuration have to be JavaScript, they can't be TypeScript, right? And so you could theoretically build all of your assets, which is also neat because stuff like Bun's bundler will build one file, right?

[00:05:07]
And you can externalize a few things, but you can say, even for your build system, each team is going to have one built asset that then gets pulled into the shell is usually a lot easier. You gotta play some games like tree shaking and in case stuff is shared, but we can figure that out. But you could also just build the types. So now TypeScript is not reading all of the code, and you're just using the kind of built-in stuff where if you are publishing a package to npm and you would like to have TypeScript support, you can have those types, exports, and then when someone installs your package from npm they would get the types.

[00:05:43]
This now the same thing works inside your monorepo, right, because each one has its own package.json. You're effectively, when we saw that workspace stuff, you're effectively pulling it in as an npm package, really. Yeah, they all live in the same repo, and they can all kind of easily share types, you don't have to publish and pull down. You're basically making a very easy way to isolate the different pieces as if you were publishing to npm and then installing them from npm without publishing them to npm and installing them from npm because that's tedious.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now