1. Introduction to ESLink and Flat Config
Hello, everyone! Thank you for being here. I'm Anthony Fu, a co-member of Vite, Vue, and Knox. I'm excited to share my findings and practices with ESLink. ESLink is a popular and constantly improving tool. Today, I'll talk about ESLinks One for All Made Easy and the new features in version 9.0, like Flat Config. If you haven't heard about it, I'll explain why you should consider using it.
Alright. How's everybody doing? Okay. Hello, everyone, and thank you so much for being here and I didn't expect we have so many of you here, so thank you.
I'm so glad to be here at JS Nation.
So, first let me introduce myself a little bit. Okay, it worked. Okay. And yeah, my name is Anthony Fu, and I'm a co-member of Vite, Vue, and Knox, and also the creator of Vite's LightDev, Uno CSS Type Challenges, and Elk. I'm also the maintainer of ESLink, StylistLink, and Cheeky2slash. I'm currently working at Nuzlab on the framework team and you can find me on the links, with the links below.
So, as you can see that I'm pretty enthusiastic about open source and driven me into working in many projects. So, I love building tools and figuring out the problems I encounter. Like, for example, like the slide you are looking at is powered by SlideF, a markdown-based presentation tool that's built on top of web technologies. It's born when I find that existing tools was not flexible enough for me to present my code. So, similarly, when I look into ESLink and its ecosystem a few months ago, I find that many things are very interesting but it's not yet fully explored. So, today I'd like to share with you some of my findings and practice during my recent explorations around it. And actually, this is, like, a 30-minute talk but I find that I only have 20 minutes, so I need to rush it and hope you don't mind.
11 years since ESLink comes out, at this moment, it's easily one of the most popular tools that's basically every project we use. And despite its being around for such a long time, it's a tool that's still consistently improving and evolving. And today, I'd like to give a board ambitious topic like ESLinks One for All Made Easy, and to share with you some of the new perspective and the patterns of using ESLink with the latest features they just rolled out.
So, you probably have heard, like, ESLink version 9.0 just released roughly two months ago, and the main highlight is the major version is rolling out the new configuration system called Flat Config. So, before we start, I'd like to do a quick survey here, like, have you ever heard about, like, ESLink Flat Config? Could you please raise your hand for me? Okay. That's a lot. Okay. And how many of you are already using or migrate to ESLink? Okay. That's a few, like, 20-something? Okay. Good. Okay. Thank you. And so, for those who haven't on Flat Config yet, so, today, I'm here to tell you why you should.
2. Comparison of Legacy ESLink Config and Flat Config
Let's compare the legacy ESLink RSA config with the new Flat Config. The legacy config uses .ESLinkRC and convention-based extents, while the Flat Config uses ESLink.config.ts and native imports. With the Flat Config, you can easily rename or switch plugins without changing array rules. It simplifies the complex tree structure of shared configs and has been in the works for five years. ESLinux has put in a lot of effort, publishing blog posts and sharing the roadmap. The biggest benefit of Flat Config is the full control and simplicity it offers in JavaScript with native imports.
So, in case you have never heard about it and here, let me do a quick comparison between the legacy ESLink RSA config and the new Flat Config for you. And to differentiate between those two configuration formats is rather straightforward, and the legacy config is named with .ESLinkRC that supports various extensions such you could have, like, .js, .jsum, or sometimes you can also read the config from your package.jsum. And in the Flat Config, on the other hand, it's only loaded from ESLink.config.ts, a JavaScript config file that's as the single source of choose.
And when it comes to reusing the shared config, the legacy config format implicitly uses a convention-based extents to load the config from your local node modules. And, by the way, this was like created before, like, we have ESL modules or something. So, you would need to learn a little bit about, like, how this convention work and to know how it's resolved and how it's mapping to the package you have. Well, the Flat Config will use native ESL import where it's more explicit and it also gives you more control. And for plugins, it takes an array of strings. It used to take an array of strings, which again is also convention-based and coupled with the plugin's package name. And now, in the Flat Config, it takes a name object for plugins. And this means you can now rename this plugin easily or switch to a fork without being forced to change array rules in your config.
So, also, the inherent nature of extents might result in very complex tree structure because the shared config can also have nettings in extent inside. So, in the Flat Config, it gets simplified a lot, where you explicitly import a shared config as multiple objects or arrays and you can compose them into a single flat array. So, that's why it's called Flat Config. So, to give a little bit more context, here's a graph I draw to demonstrating the timeline. While the Flat Config might sound new to some of you, it actually has been planned for five years already. The RFC was created in January 2019 and the first implementation is available in version 8.21 as experimental, which is two years ago, and become stable in 8.45 and now it becomes default recently in V9. And in between, ESLinux has pushed a lot. It's also like a published multiple blog post to explain the reason why they want to introduce the new format and share the roadmap of rolling out plan. And that's a lot of effort spent across these five years' plan. So, huge respect to the ESLinux team. And as we mentioned in a previous slide, the biggest benefit of Flat Config now is in JavaScript where you have full control and also use native imports to resolve the plugins and the configs, making the inheritance and overriding a lot simpler.
3. New Possibilities with Flat Config and Tools
The Flat Config has been in the works for five years and recently became the default in version 9. It offers full control and simplicity in JavaScript with native imports. Shared config can now be a factory function, allowing users to customize their configs. A migration tool, ESLink/migration config, automatically converts legacy code to the Flat Config. The ESLink config inspect tool visualizes the final resolve config, allowing easy inspection and understanding of each config item.
So, to give a little bit more context, here's a graph I draw to demonstrating the timeline. While the Flat Config might sound new to some of you, it actually has been planned for five years already. The RFC was created in January 2019 and the first implementation is available in version 8.21 as experimental, which is two years ago, and become stable in 8.45 and now it becomes default recently in V9. And in between, ESLinux has pushed a lot. It's also like a published multiple blog post to explain the reason why they want to introduce the new format and share the roadmap of rolling out plan. And that's a lot of effort spent across these five years' plan. So, huge respect to the ESLinux team. And as we mentioned in a previous slide, the biggest benefit of Flat Config now is in JavaScript where you have full control and also use native imports to resolve the plugins and the configs, making the inheritance and overriding a lot simpler.
And because it's fully in JavaScript, shared config can now be a factory function that's taking users' options. And the user could have a lot capability to customize how those configs being composed to their specific needs. So, before talking about exciting new stuff, let me first quickly go through the tools for migrating the legacy config to the new Flat Config, in case you might need them. We recently have a COI called as ESLink slash migration config that automatically converts your legacy code to a Flat Config. And some runtime utilities for compatibilities were being introduced automatically along the way. So, I would recommend you to check the ESLink docs for migration guide for more detailed instructions because I'm running out of time.
Okay. And now, so let's talk about the interesting new tools and how it's enabled the new possibilities with the new formats. So, the first one is the ESLink config inspect, a visualized dev tool that allows you to inspect and play with your final resolve config. And you can run it by running ESLink dash dash inspect config in your COI that's under the project route where you have the Flat Config. And it opens a browser page with the UI as the one you see on the right. And, yeah.
The first thing it does is renders each config items you have, and you can see all the config listing here because it's flat. And it's a, here I have a like a rather complex config with many config items. But with the name provided by each config, you can easily see and understand the purpose of each of them. And you can also expand the items to see how it's contribute to these final config. So, here like you can see these rules like I have installed these plugins and a few rules. And also, I can click on the, here I have a, like a short description of the rules. And also, I can click in to see there's a link to the docs. Okay. You can find that's how this being set. And also, like you can see that's how it's contributing to the languages and also, I mean, a lot of things.
4. ESLink Config Inspection and Customization
ESLint allows applying different rule sets for different file types or paths. The ESLink config inspect tool visualizes the final resolve config and lists all the installed plugins and rules. You can filter rules by recommended or unused, and check for deprecated rules. Config files can be a factory function with high-level options, allowing customization. TypeScript rules can be enabled/disabled, and type-aware rules can be provided with TS link and TS config paths.
And so, you can see that, okay, this JSON is also apply for the files for the JSONs. And so, since in ESLint you can have different, okay, I mean jumping around to monitors. Okay. Yeah. And also, like you can also have a file tester here to say that's if I would like to see how my file is being matched because you know that's in ESLint you can have different rule sets apply for different file type or like more granularly like each exactly file path or file name upon a choice with a goal. So, you can enter, you can enter the file name here like to say if I want to check for app.view. So, you can see that's how these rules being matched and those are specific to view and here is that because view is also on this, it also support TypeScript. So, TypeScript rules is so enabled for view as well. And you can also have like, you can also like, here you have a type complete, autocomplete. And you can have a package of JSON like I enable JSONC rules for it. So, now you can like basically have better understanding of how your rules are working in your project. And here you can also have another tab called rules that's listing all the plugins that you installed and all the rules you have from those plugins. And here I'm seeing the use but you can click all which is like all the rules available but you are not using. Here like the right one is the one I'm using and here is not, I'm not using. And also you can filter with the recommended. So, you can see that I can say like unused recommended. And those are like the rules that's recommended by the plugin also but I didn't enable it. And then you can go through to see if you should enable it or like there's a lot of things you can do also like here, you can click it and you can see all the deprecated rules that you probably need to migrate as well. So, so this just give you a quick like overview of what is these things. And here is the, here is the config files I have for example. And this is actually live link to the, to the, to the dev, to the inspector. Yeah. And so here like, because like flat config can be like the config can be a factor function that takes rather high-level options. So, here I have the config that called antfu is my config and it's exposed a few options here. So, here we can see that I have TypeScript rules enabled but I can actually, I can just change to false. Okay. And disable it and you will see the TypeScript rules is gone. And also I can do more. It's like, I can make, make an object. So, if I want to have like a type-aware rules, like I can provide TS link, TS config pass and okay.
5. Config Customization and Type Generation
The ESLink config utilities library provides a compose function that automatically resolves different types of config, including promises. It also allows for inserting extra config and overrides, making customization easier. With the full context available in flat config, type generation becomes possible.
So, yeah. It's hard. And when I, when I save it, you will see that here I enabled the type-aware parsers and also the types-aware rules. And those are like the high levels though, so the end users of this config doesn't need to care about like how it works internally. So, I will try, I will explain this a little bit more further.
Okay. I'll just get back my mouse. Okay. So, to make configuration, to make config customization early, easier, I also made a small library called ESLink flat config utilities. For example, like here is the flat config that we might have, depends on how you shared config is construct. Some might be a planned config object, some might be an array, and some might be a constructor that returns an object, an array, or even promise, where you need to resolve them and flat them into a single array.
So, in that case, you are responsible to join them together. And with the, with the config utilities, I made a utility function called compose which will automatically resolve different types of config. So, it also resolve promise and merge them together. So, in that case, you can basically not really need to care about like what is the format of the config. And it's also provide a channelable action where we can insert extra config anywhere you want or override some config without like need to handle the merge manually. And then, thanks to the flexibility and having the full context available in flat config, it also make the type generation possible.
6. Maximizing Flexibility with Flat Config
By wrapping the entire config array with the type gen function, you can generate a local DTS file for auto-complete and type check. One for All: a single config that covers all types of projects. Flat config allows semantic options to toggle features dynamically. It provides a minimum configuration interface like prettier, while still offering full control when needed. It also enables meta frameworks like Nuxt to generate sub-configs based on user project setup.
So, simply by wrapping the entire config array with your export to the type gen function, which I didn't show you here, but it will generating a local DTS file based on the plugins you have installed. And it will provide you the auto-complete and type check for all the rules you are using. And that is like you don't need to have the ESLink plugins working for TypeScript. But you can, you can make it work on your, on your user land for any plugins.
And so here, I'd like to bring back the title One for All, which is maximize the flexibility and the customization, customizability. And it's now possible to have a single shared config that covers all different types of project. So, I can do a quick comparison here to show what I mean. And in a new flat config, a shared config can be a factory function that takes user option which we couldn't do that in the laxic config. Imagine if my config, I want my config to work on both TypeScript and non-TypeScript project, a view and non-view project, I would need to do a monoreport to publish those different config for different combinations. And as you can see, it doesn't really scale well because they're doubling and the amount of combination for each options. I may later want to have a React and TS React version. So, the flat config allows you to provide a semantic option to toggle each features dynamically and making one single config to be adoptable.
So, because of that, we could also have high level abstractions to absorb the underlying complexity and it provides the minimum configuration interface like prettier, which the end user don't need to keep worry about the underlying details while we still have the full controls as we still have the full controls when user really want to do. So, I say that it's like a minimum configuration as prettier but still as powerful as customizable as ESLint. Yeah. So, flat config also made it possible for meta framework to provide a project where config. For example, like in Nuxt, we have a file-based routing, auto-import components, server-side, server API directories. I mean, each files under different folders with different names might have different purpose or different constraint. So, in Nuxt, we had the ESLint, Nuxt ESLint module, which is generating a sub-config based on the user's project setup where user can extend from and can add their own custom rules on top of it. So, this is just like one direction of possibilities with flat config we are currently exploring. But we believe that we will have a more interesting approach coming from the community given flat config is still quite new.
7. ESLint as a Formatter
ESLint is more than a linter. It can also be used as a formatter. Despite controversy, using ESLint as a formatter offers flexibility and customization. Last year, stylistic rules were deprecated from the core, and a community project was initiated to maintain them. Personally, I find ESLint more flexible and customizable than prettier.
And, okay, I have a few minutes. Okay. And the other topic I want to bring up today is like the fact that ESLint is actually more than a linter. To me, I see ESLint as a mature and powerful AST toolkit that has a large ecosystem on its back because we have all the integration for different IDEs, et cetera. So, the first is like ESLint can be a formatter. And this is rather, it's certainly not new. I mean, as many project has already been using ESLint since very beginning. While this topic is actually a little bit controversial, which you might hear people saying that you should use a dedicated formatter is like prettier or deep print, to me, I see this all down to those stylistic rules for ESLint that takes a lot of maintenance effort. So, last year, ESLint and the TypeScript ESLint team has decided to deprecate all those stylistic rules from the core. And then I initiate the ESLint stylistic projects gathering all those stylistic rules that's for JSTS, JSX into these organizations and we have a community to keep maintaining them. And so, I'm personally, I'll keep using ESLint as a formatter as I see is much more flexible and customizable than prettier and due to ESLint's nature. So, if you are using like a like here I have a stuck.
8. ESLint as a Tool for Code Mode
If you're using VS Code, you can set the editor code action on save to auto fix ESLint errors and use customizations to silence stylistic rules. ESLint can also be used for codemode with the help of ESLint plugin commands. Magic comments can automatically convert code upon save, and other features like sorting, removing duplicates, and regex hoisting can be achieved. This toolkit provides more control and customization options for code mode.
Okay, yeah. Here I have a small tip. Like if you're using VS Code, you can set the editor code action on save to auto fix ESLint errors and then you can use ESLint rules customizations to silence stylistic rules in your ID so you don't gather this like error lines for stylistic rule. While that you can still gather auto fix features from your ID. And I'm mainly working for, I'm mainly using VS Code so probably there's a similar option for the other code editors.
So, why ESLint rules is essentially a function to, while that's ESLint rule is essentially a function that's take code and AST and report errors and optional fix information. So, it doesn't really has to be linting. So, which means is ESLint can be also be a nice tool for codemode. Like for example, I made the ESLint plugin command which do on demand micro codemode. So, here I can play a video. I hope I still have time.
Okay. Okay. So, as you can see here at the video, it's like I can put a magic comment to say that to function on top of an error function. Upon save, it automatically converted into a function declaration without me to manually move these things around. You need to remove the errors or something. And similarly, you can also like have a keep sorted and on top of an object, so you can always keep it sorted. Okay. You can have like a keep unique to an array to make sure that it's automatically remove all the duplications. And here, we can also have like a hoisted regex on top of regex. We give a name. When you save it, it will host your regex into the top level to kind of like a performance improvement or something. And also, you can have it. You can turn in if else into a tannery. You save it, please. And then you can have a lot of things. Those are just like a few examples. And also this can be very customizable and you can provide your own custom command with just like if you know a little bit about AST, it shouldn't be hard for you to write it like a one of rules. Even for like migrating your code base because you also have the reporter and also because ESLint has a reporter and you can decide when you save these files and you can also ignore it. It's like a basically, you have more controls and all this toolkit is already for you to do the code mode.
ESLint for Other Languages and Mono Repo Configs
ESLint can be used as a linter for languages other than JavaScript, such as TypeScript, Vue, Svelte, Astro, and JSON. It also has support for YAML, TOM, graph, HTML, and MDX. Additional plugins like the ESLint plugin format provide formatting capabilities. Check ESLint RFC number 99 for more language agnostic support. With ESLint, you can have one config for all projects and use it as a tool for code checking and modifications. For more details, refer to the speaker's personal ESLint config. Thank you for attending the talk!
All right. Okay. Go back. Go back. Where's my mouse? Okay. All right. And finally, I would like to mention ESLint can also be a linter for many other languages other than JavaScript. As you probably know, that's TypeScript ESLint is make ESLint understand TypeScript and TypeScript is not a JavaScript, by the way. And also we have like ESLint config view for view single file components, ESLint plugin for Svelte components, ESLint plugin Astro for Astro and also have the ESLint plugin JSON files. That's which is very handy for me to say that I can sort a certain fields in a certain JSON file. For example, I'm keeping my dependencies listed. I'm using this rule to keep my package of JSON dependency list always sorted. And similarly, we also have support for YAML, TOM. As you can see, there's many of those tools that are coming from OTA, Meshi. So, he's truly amazing and also have a graph ESLint and HTML ESLint, ESLint MDX and I also recently made an ESLint plugin format which use prettier or deeper into format files that CSS. That's not fully have the ESLint integration but you can use it for formatting. So, that's only a few I could list here and you can also check the ESLint RFC number 99 which they are trying to make ESLint as a more language agnostic to support ESLint for more languages easier.
So, to summarize today's topic, I would like to say ESLint make it possible for be one for all in two aspect. As you can see that, you can have one config for all project and also like, they can be a one tool like for everything that related to code checking and the modifications. So, if you want to learn more, you can check my personal ESLint config which I use all the tricks I mentioned today. I'm only a bit flattered to see that even though I didn't intended to have this config to be used by the others, it end up to be quite popular to have 3,000 stars over like 30,000 projects on GitHub is using it. So, I wasn't trying to like sell my config to you but hopefully it can give you a good reference for you to build your own shared config that can be both powerful and flexible. So, thank you. And that's all for my talk. You can find my slide at NTFU. All right. Can I see it? So, how does the new flat config work on a mono repo repository? Can we only have one config with it or can we have multiple configs? I mean, by ESLint itself, it's usually take one ESLint config. So, there's like two ways of doing that is like you have a multiple ESLint config and you run ESLint in multiple packages. It's like but that's not efficient and what you could do is like in my flat config utilities, you can have extend which you will rewrite all the paths you have for the ESLint config. So, you can have multiple config and you extend each other so it will be automatically convert to the path of specific to that project.
Migrating to Flat Config
Migrating to flat config can be challenging due to the lack of plugin support. The latest ESLint announcement includes compatible packages and tools to help with migration. Check the latest documentation for more information.
So, you can still possible, you have a single file but you can extend from multiple one with a specific path. Nice. This one is very useful because it's something. I found migrating to flat config is hard because many plugins do not support flat config yet. What do you advise people should do? I mean, when ESLint first come out like two months ago, the tooling is a little bit lacking behind and recently they announced a few compatible packages like one is fixing the plugin API and one is converting automatically and also you can also use the previous extend with like a flat config compact or something and you can do that. I failed to mention it in my slide but definitely check out the latest docs. Should be have enough information for you.
ESLint and Prettier Integration
ESLint can be used alongside prettier, offering more flexibility and control. The tools can work together as long as conflicts are disabled. Finally, the speaker is asked about the presentation software and IDE embedding, which are praised.
Okay. So, it's a, there is new docs there that will help you through that? Yes. Otherwise, you can send a issue to there. I mean, they are doing a migration tool. They should, we are ready to help. We are like developers to just open lots of issues and annoy you. That's open source and you have... All right.
Next one. How are you keeping up with the cross tool development integrating with prettier, for example? And I guess you touched off this with the... Like, is the new version going to replace prettier or because you have the ESLint style int? Or are you still going to play nicely with prettier as far as ESLint is concerned? Yeah. You can definitely use ESLint with prettier if you need it. Okay. It's like... I think it's more like a personal choice. You can like using different formatter to do the formatting. And for me, like... Yeah, it's like because I think like ESLint has more flexibility than I want because prettier, you know, is famous of like being very minimal configuration, which is great. But when you have more... When you want more controls, it doesn't really work for you. So I'm a big opinionated person. I want all controls of all the things. So ESLint is something that's helped me to better achieve that. So I mean, it's definitely okay if you prefer using prettier. All the tools should be working. You just need to disable the conflicts. Yes.
Nice. So there's one last question I really want to ask because I was also curious about this. What presentation software are you using? And how does this IDE embedding work? Because what an incredible presentation.
Presentation Software and IDE Embedding
The presentation software used is SlideF, built on top of Vite and Vue, with markdown-based slides. It allows embedding applications, using components, and creating interactive components. The IDE used is Monanko with TypeScript setup. The slides are displayed through an iframe, linking to another page.
It was really cool to watch. Thank you. Yeah, it's called SlideF, which is built on top of Vite and Vue. And you can... It's basically markdown based. So basically, when I'm working on slides, I'm working on markdown file. And I'm using something like a separator to separate my slides. And then I can do anything I want with the web. So you can embed an application if you want. You can use components. You can do interactive components. And the IDE I have is Monanko. And I set up TypeScript for it. And the rights is actually iframe, linking to another page. So that's how it works. Yeah. Fantastic.
All right. I think that's all the time we have for on this session. One more round of applause, please, for Anthony. Thank you. Wow. Fantastic. ♪♪♪
Comments