Enforcing Rules
Linting your Code
— 4 minPreviously I have written extensively about the problems I face and some ideas how I would like to organize a larga codebase.
Another challenge is to integrate this all into a monorepo but in a way that best isolates new code from old code. Best way to do that is via linting, so lets look at that in more depth.
Put very simply, a linter is a tool to enforce certain rules on your code. From formatting concerns to more sophisticated rules such as making sure that you handle async promise-based code correctly.
Linting can happen at a few distinct phases during development:
- During development inside an IDE, which can point the developer to problems immediately, and can do formatting and fix some auto-fixable lints directly at format on save time.
- At commit-time via a pre-commit hook. To make sure developers only commit valid code.
- On a CI server, to make sure that only code that conforms to the set of rules will land in the repository.
These use-cases are also listed in the order of responsiveness expectations. The in-editor usage should be instant, while on the other hand you don’t really care how long linting will take on CI.
And here comes the problem that I already mentioned in my previous posts. I suspect that my editor integration via typescript-tslint-plugin might be the cause why the language server frequently becomes super slow, and might even reliably OOM when I change a lot of files at one, for example by changing branches.
Also the pre-commit hook is super slow depending on many files are being changed.
One reason for this slowness might be that the linter needs to start up from scratch every time, and needs to typecheck the code again every time. There is no way to share some state between these tools.
Back in the days when I was still using vim, I used eslint_d which starts a long running process and communicates with that via a socket. That way it can avoid all the startup and warmup costs of node. (One very good reason why you should bundle your code as much as possible)
One of the problems with at least the vscode
integration of tslint
was that
it did not support rules that relied on typechecking. That was the main usecase
of typescript-tslint-plugin. But now tslint
is officially deprecated in
favor of typescript-eslint.
I haven’t tried that one yet, but I do know that there is no deep integration
with the language server yet, I have
asked specifically.
And I am not sure yet if the eslint
plugin of vscode can correctly work with
rules that depend on typechecking. I would like to think that it does.
But even so, that would make things even worse, since it means I would have two
long-running processes in the background, both doing redundant work. Maybe someone
will write a tsserver
integration at some point, maybe even myself.
But enough about that. The challenge at hand is to isolate code inside a monorepo in a way that can guarantee to you can’t cross the import barrier from new to old code.
I hope that a combination of eslints no-restricted-imports together with
eslint-plugin-import
s no-restricted-paths will be enough in that regard.
Other than that, I think the story here is quite good. I still need to spend some time evaluating all the linting rules we have, again. :-D