Make imports more readable. JS/TS and ESLint solutions.

dmitriiprusakov

Dmitry Prusakov

Posted on May 11, 2023

Make imports more readable. JS/TS and ESLint solutions.

Introduction

Many challenges are encountered as a product scales. One of the most important is to ensure code maintainability. The depth of imports increases as the codebase grows. They becoming to look really messy.

Sometimes your imports become looks like this, especially in complex projects. Just look at those imports, it’s really difficult to understand.

A lot of slashes and periods "../../../../how/deep/are/those/omg"

A lot of slashes and periods "../../../../how/deep/are/those/omg"

In this article, I will not touch architecture and dependency injection, but will simply talk about how imports can be made more readable.

In a Unix-style file system, a period "." refers to the current directory, a double period ".." refers to the directory up a level. By default, if we need to import something from up level directory we need to write it as relative path. Like, from current directory we need to jump to 3 levels up and find here specific file: "../../../service/{filename}".

But what if I say, that we can actually write imports as non-relative paths like "app/service/{filename}".


First solution – Path mapping via JS/TS compilers

My friend notices the same problem with messy imports and remembered “aliases for imports”, but he got some difficulties.

Chat with my friend about messy imports problem

Screenshot of chat with my friend about messy imports problem

So let’s try to beautify our imports with first solution.

JavaScript and TypeScript compilers resolving our relative imports, but we can change configuration to make it resolve non-relative imports too. So we just need to add «baseUrl» and «paths» directives in jsconfig.json or tsconfig.json file.

Setting «baseUrl» informs the compiler where to find modules. All module imports with non-relative names are assumed to be relative to the «baseUrl».

And via «paths» we setting up compiler to use a mapping configuration to map module names to files at run-time.

Imagine we have file structure like this, so we can apply config like this:

Example of file structure and equal configuration below<br>

Example of file structure and equal configuration below

So we can apply config like this:

{
   "compilerOptions": {
      "baseUrl": ".",
      "paths": {
         "@features*": [
            "./features/*"
         ],
         "@core*": [
            "./core/*"
         ],
         "@auth*": [
            "./auth/*"
         ],
         "@store*": [
            "./store/*"
         ],
      },
   }
}
Enter fullscreen mode Exit fullscreen mode

Please notice that «paths» are resolved relative to «baseUrl».

This configuration will give us readable imports like this. We got rid of periods and slashes.

Nice imports with non-relative paths by manual config for JS/TS compilers

Nice imports with non-relative paths by manual config for JS/TS compilers

If you noticed, we still can use relative paths as well as non-relative. My personal preference is to use non-relative paths for deep imports to another logic parts of project, and use relative paths for 1–2 level imports within a current logical part.

Looking good! But we have to manually configurate it.

And next solution will work automatically. So comment your «paths» directive and move forward!


Second solution – ESLint import resolver

ESLint is super powerful tool! And it's also has plugin for linting import/export syntax. And there is also imports resolver than can help us with to upgrade our imports.

We need to install eslint and import plugin:

yarn add --dev eslint eslint-plugin-import
Enter fullscreen mode Exit fullscreen mode

And add this configuration in ESLint config file:

{
  "settings": {
      "import/resolver": {
         "typescript": {
            "project": "./tsconfig.json"
         },
         "node": {
            "paths": [ "." ]
         }
      }
   }
}
Enter fullscreen mode Exit fullscreen mode

And that's all!

After this we getting automatically resolved non-relative imports!

Nice non-relative imports resolved by ESLint import plugin
Nice non-relative imports resolved by ESLint import plugin


Thanks for reading this article! By following it, you’ll develop more maintalable code with readable imports. I hope it will help you to develop greatest projects!

I’m progressive software engineer with over 5 years of development experience and I love to share it! So follow me and stay tuned!

Incoming topics:

  • WebAssembly (Wasm): when and how to use it
  • Client API code-gen, from OpenAPI Specs to TypeScript
  • Getting frames from video files on frontend

References:

💖 💪 🙅 🚩
dmitriiprusakov
Dmitry Prusakov

Posted on May 11, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related