<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dmitry Prusakov</title>
    <description>The latest articles on Forem by Dmitry Prusakov (@dmitriiprusakov).</description>
    <link>https://forem.com/dmitriiprusakov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1080399%2F06e4b6ee-fdf0-4bdc-8a8e-c06d795639d5.jpg</url>
      <title>Forem: Dmitry Prusakov</title>
      <link>https://forem.com/dmitriiprusakov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dmitriiprusakov"/>
    <language>en</language>
    <item>
      <title>Make imports more readable. JS/TS and ESLint solutions.</title>
      <dc:creator>Dmitry Prusakov</dc:creator>
      <pubDate>Thu, 11 May 2023 20:49:06 +0000</pubDate>
      <link>https://forem.com/dmitriiprusakov/make-imports-more-readable-jsts-and-eslint-solutions-2n27</link>
      <guid>https://forem.com/dmitriiprusakov/make-imports-more-readable-jsts-and-eslint-solutions-2n27</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;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. &lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil0pqpt3o5lols9cgj0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fil0pqpt3o5lols9cgj0j.png" alt='A lot of slashes and periods "../../../../how/deep/are/those/omg"' width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;
A lot of slashes and periods "../../../../how/deep/are/those/omg"







&lt;blockquote&gt;
&lt;p&gt;In this article, I will not touch architecture and dependency injection, but will simply talk about how imports can be made more readable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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}".&lt;/p&gt;

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




&lt;h2&gt;
  
  
  First solution – Path mapping via JS/TS compilers
&lt;/h2&gt;

&lt;p&gt;My friend notices the same problem with messy imports and remembered “aliases for imports”, but he got some difficulties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh3sl68c7mv8j4w6pwph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh3sl68c7mv8j4w6pwph.png" alt="Chat with my friend about messy imports problem" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;
Screenshot of chat with my friend about messy imports problem






&lt;p&gt;So let’s try to beautify our imports with first solution.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Setting &lt;strong&gt;«baseUrl»&lt;/strong&gt; informs the compiler where to find modules. All module imports with non-relative names are assumed to be relative to the «baseUrl». &lt;/p&gt;

&lt;p&gt;And via &lt;strong&gt;«paths»&lt;/strong&gt; we setting up compiler to use a mapping configuration to map module names to files at run-time.&lt;/p&gt;

&lt;p&gt;Imagine we have file structure like this, so we can apply config like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7y1vx9d4e4vevmnfvwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7y1vx9d4e4vevmnfvwl.png" alt="Example of file structure and equal configuration below&amp;lt;br&amp;gt;
" width="308" height="537"&gt;&lt;/a&gt;&lt;/p&gt;
Example of file structure and equal configuration below





&lt;p&gt;So we can apply config like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"@features*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"./features/*"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"@core*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"./core/*"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"@auth*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"./auth/*"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"@store*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"./store/*"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Please notice that «paths» are resolved relative to «baseUrl».&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This configuration will give us readable imports like this. We got rid of periods and slashes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0czx2x0fq14q0i0yn5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0czx2x0fq14q0i0yn5e.png" alt="Nice imports with non-relative paths by manual config for JS/TS compilers" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;
Nice imports with non-relative paths by manual config for JS/TS compilers






&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Looking good! But we have to manually configurate it. &lt;/p&gt;

&lt;p&gt;And next solution will work automatically. So comment your «paths» directive and move forward!&lt;/p&gt;




&lt;h2&gt;
  
  
  Second solution – ESLint import resolver
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;We need to install eslint and import plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; eslint eslint-plugin-import
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add this configuration in ESLint config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"import/resolver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"project"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.json"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's all!&lt;/p&gt;

&lt;p&gt;After this we getting automatically resolved non-relative imports!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtjeq7mshv3kl1kobnch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtjeq7mshv3kl1kobnch.png" alt="Nice non-relative imports resolved by ESLint import plugin" width="800" height="321"&gt;&lt;/a&gt;Nice non-relative imports resolved by ESLint import plugin&lt;/p&gt;




&lt;p&gt;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!&lt;/p&gt;

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

&lt;p&gt;Incoming topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebAssembly (Wasm): when and how to use it&lt;/li&gt;
&lt;li&gt;Client API code-gen, from OpenAPI Specs to TypeScript&lt;/li&gt;
&lt;li&gt;Getting frames from video files on frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/eslint-plugin-import"&gt;ESLint import plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html"&gt;TypeScript module resolution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/tsconfig#paths"&gt;TypeScript docs: paths&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
