The Joy of JavaScript Absolute Imports
Absolute imports are an essential developer experience feature for me in any JavaScript application. In this post, I’ll explain what they are and why they matter.
What Is An Absolute Import?
It’s easier to think of an absolute import in contrast to a relative import, which looks like this:
import { Page } from '../../views/pages/Page';
Translating this code into words:
“Bring in the named export
Page
, which can be found ‘up’ two directories and then inside theviews/pages
directory.”
Here’s that same import with an absolute path:
import { Page } from 'views/pages/Page';
In words:
“Bring in the named export
Page
, which can be found in theview/pages
directory.”
That directory is relative to some place we don’t know about. Typically it’s the src/
directory, but we can’t say that with just this much information.
The difference between these two statements is subtle; just a few characters. It’s configurable on every kind of JavaScript and TypeScript project I’ve worked on. Google “absolute imports in X framework” for the implementation in your framework.
Why Are They Great?
I love absolute imports, and strongly prefer them! Here are a few reasons why.
First, absolute imports auto-complete well. I use Vim’s ctrl-x ctrl-l
to
autocomplete my import statements, which compares what I’ve
typed so far in a line against other lines in my project, suggesting completions
that I can tab through. Our absolute import is the same regardless of where
Page
is imported, which lets our autocomplete give me a correct suggestion if
it’s ever seen a similar line before. Relative imports won’t work this way
reliably, because my text editor is going to suggest a relative path that’s not
necessary correct given my current buffer’s location.
Second, absolute imports let me easily move files around. When all imports are absolute, there’s less friction to moving a file, because all of the imports will just boringly work in the new directory.
Third, absolute imports scale well. A large React component is typically going to have a lot of imports:
import { AboutUs } from '../../../views/pages/AboutUs';
import { Blog } from '../../../views/pages/Blog';
import { Dashboard } from '../../../views/pages/Dashboard';
import { Login } from '../../../views/pages/Login';
import { Navbar } from '../../navbars/Navbar';
import { PasswordReset } from '../../../views/pages/PasswordReset';
import '../../../stylesheets/Dashboard.scss'
What value are these dots and slashes providing? Remove them and I think readability increases:
import { AboutUs } from 'views/pages/AboutUs';
import { Blog } from 'views/pages/Blog';
import { Dashboard } from 'views/pages/Dashboard';
import { Login } from 'views/pages/Login';
import { Navbar } from 'navbars/Navbar';
import { PasswordReset } from 'views/pages/PasswordReset';
import 'stylesheets/Dashboard.scss'
Most importantly, absolute imports decouple my code from the directory
structure. The location of Page
relative to where it’s imported is not
important enough information to encode. Or spend time thinking about.
An Exception For Co-Located Stylesheets and Tests
Even with absolute imports as a convention, I still use relative imports occasionally. One use case is a React app with co-located stylesheets and tests. In a directory such as this:
Relative imports are arguably a helpful convention for the co-located files:
// Component.jsx importing its stylesheet
import { styles } from './Component.module.scss';
// Component.test.jsx importing its test subject
import { Component } from './Component';
Conclusion
For an exploration of JavaScript imports, check out my post on the subject, How to Organize JavaScript Imports. I strongly recommend absolute imports for a more joyful JavaScript coding experience.