Scottish Technology Club Logo Scottish Technology Club

LinkedIn · Bluesky · X · Community Discord

Linters DIY

Kat Kmiotek
15th October 2024 · via GlasgowJS

Transcript

So our next speaker is going to talk about a topic that maybe isn’t quite as flashy as TresJS, but is just as important. Linting is one of those things which we never really appreciate until everything absolutely goes wrong.

So Kat here is now going to give you a quick talk about linting and make sure that after this you’re using it in all your projects. So please give a round of applause for Kat Kmiotek.

APPLAUSE

Okay, hello everyone. Sorry, my name is Kat Kmiotek. I work as a quality engineer at Houseful.

Houseful is a brand behind Zoopla, behind Alto, Prime Location, Yorkie, Skalkasa. So if you are looking to buy, sell, rent or let the house or flat, you probably use one of our tools. And today I’ll be talking about linter DIY.

So I’ll explain how linters work. I assume that some people in here use linter day to day, some people maybe not. So I will go through what it is, how to use it, why to use it, and then we’ll dive into more complex configuration of linter and how to get the most of it.

As an example, what we’ll be talking about, the linter I will be talking about is the ESLint library, NPM package.

So yes, what is linter? Linter does static code analysis, so it means that your code doesn’t need to be executed for linter to highlight the issue and to run against your code. And linter detects potential syntax errors, you misspell something or security issue when you try to commit the security or GitHub document to the repository, or can flag possible performance concerns when you try to infinite loop.

So it can be used to ensure consistent formatting across the project, and some of the IDEs already have it built in. I’m not sure if you work with Visual Studio or with IntelliJ, they already have the linter built in. But here we are talking about the ESLint, so the package that you install as a separate dependency in a package.json.

Why to use linter? So as I said, it enforces the consistent code formatting across the project with the potential issues. But imagine that, so I’m talking about my example when I work as an automation engineer. We have, and it’s common that automation engineers come from different backgrounds, some work in Python, some in Java, and here we made more work on the JavaScript project. Each of us is different, we don’t call it coding style, I would call it habits, let’s say from Python or from Java, how we let’s say call variables and so on. So we would agree on a constant, consistent formatting and rules for our project. This way we would have consistent, readable, and easier to maintain code. Whoever joins our team will find it easier to pick up what is happening in the code base because everything is just nice to read.

In my opinion, using linter in your project speeds up release cycles. I don’t know if you ever had PR comments like missing semicolon, extra whitespace, await missing, something like this. In my opinion, it’s like this pull request ping pong, where it’s back and forth, back and forth. A PR can take one day, even for just a small change. Once you have linter fixing those small issues for you before you submit your PR, you can be sure that the review is focusing on the code logic rather than the formatting.

And of course, by having linting running consistently on our code base, we can prevent some of the bugs from getting to production. An example from my automation experience: I mostly work with Playwright. Playwright is async, so if you miss an await, it basically doesn’t work. You can set the linting rule to highlight hanging promises and flag it when await is missing in your code base. That’s really helpful.

When you run linting, npx eslint and path to the file, that will output in the console the errors and warnings. They are based on your configuration. So whatever your configuration says, linter will search the code base for those issues.

Just a few examples here: let’s say there’s a second one, my var is assigned a value but never used. You declare a variable somewhere in your code base but forgot to use it, or maybe you meant to use it but actually referenced a different variable later on. There’s also the hanging promise and a couple warnings from Playwright. Playwright has its own ESLint plugin as well. Page wait for timeout is not the best practice to use in your production code as it’s basically a hardcoded wait. We try to avoid it, so that would be a warning. And that’s how the console output looks.

When you have your file open in, let’s say, VS Code, linter would highlight the issues for you, like declaring a variable but never using it, duplicated exports, or trying to reassign a const. The warnings would be underscored in orange. Linter can suggest how to fix the issues if they are fixable, such as converting const to let so you can reassign the value. Or you can skip the rules, ignore the next line, or ignore that issue for the whole file.

Configuration of the linter is what it respects as decided by you or your team. You can create custom rules. You would probably extend from recommended plugins, but if your project is framework-specific, like React or Vue, you can install plugins like eslint-plugin-react or eslint-plugin-vue. And you will be following best practices recommended by those frameworks or by tools like TypeScript. I work mostly with Playwright. There’s also an ESLint plugin for Playwright with a recommended set of rules.

Some big names have open-sourced their ESLint configurations, which is cool. You can install Airbnb’s plugin in your codebase and code like an Airbnb or Google engineer. I used to do that but realized I kept skipping or changing the rules, so I thought maybe they’re too opinionated for me. But I would recommend checking them out to see if they match your needs.

When you add linting to your project, there are some considerations. Some people like it, others find it an obstacle to committing code. I’ve heard that errors appear as you code, which is true—it’s a context switch when the linter highlights an unused variable in the middle of something you will eventually use. You can configure linter to run on save or disable it entirely and run linter only at the end. This is up to you.

I often skip rules. For example, on one project, we had to add page wait for timeout in Playwright due to the app being slow, and we kept skipping that rule. So we asked, is there a point to having this rule if we keep skipping it? You can control this with configuration.

Adding linter to mature projects is a big task. If you’ve tried it, you know even a basic configuration might require a lot of refactoring. I’d advise ensuring sufficient test coverage beforehand or planning it as a small migration task. But adding linter will benefit the whole team.

To level up your linting, you could reuse your configuration. You can create your own NPM module and publish it to the GitHub registry or NPM. Maybe your team will create a custom package, like Airbnb or Google. You could also create custom rules for your specific project. ESLint docs are really good for guiding you through creating custom rules and deploying your NPM package.

A linter parses code into tokens, which are translated into nodes of an abstract syntax tree (AST). This is important because many tools, like code coverage tools, security scans, compilers, and IDEs, rely on ASTs. The website AST Explorer can help you visualize this process. You can paste your code and translate it into a tree. To experiment, I use Espree, an NPM package for console logging variables.

Before finishing, I wanted to mention that I like pre-commit hooks. Fixing issues before committing them is a good idea. I use the pre-commit package, a Python package, for Node projects. Combining linting and pre-commit for multi-language projects is effective.

Thank you. That’s all from me.

APPLAUSE

And also, we are hiring! We’re looking for React and .NET developers. You can visit our website.

Awesome. Thank you very much, Kat.

Honestly, I have to say I’ve never seen someone’s face light up as much…

[LAUGHTER]

…when you say abstract syntax tree.

[LAUGHTER]

Do we have any questions for Kat?

My question is, does ESLint run at compile time or run time?

It runs before. It’s not executed as part of the build—it runs before that.

That’s compile time. If you’re adding it to your project, check out the ESLint docs. They provide step-by-step instructions.

Last question: does ESLint detect SQL injection vulnerabilities?

I’d recommend using SonarQube for that. It can detect such issues by parsing the syntax tree.

Thank you.

Any other questions about ESLint?

Hi, I had a question about the AST part. Does it create the AST per file or analyze thousands of files?

When you run ESLint, you can specify which files to lint. It could be all TS or JS files within a path.

That makes sense. Thank you.

Thanks for the presentation. What is your vision for the DIY linter you’re building?

That was more a guide for building your own rule. If your team agrees not to allow certain imports, you could create a rule for that.

One more thing. I’ve worked with ESLint, and I found it overwhelming because of the many rules. How do you set up the configuration?

That’s a good question. I’d start by extending the recommended framework rules and discussing with the team what works.