Catalin Ciubotaru avatar

Organise imports with Prettier and friends

Feed your internal perfectionist by having perfect import hygiene.

The Problem

Nowadays, we work with javascript or typescript modules, and we almost always end up having quite a few imports in each file. Sometimes, it ends up being quite difficult combing and understanding which import brings what in. To make it even worse, it adds to the unnecessary noise that each PR is already struggling with.

Good to know before jumping in

Most IDEs worth their salt know how to at least remove imports that are not used in the file, I highly recommend using that option since it helps stay clean. TsLint(R.I.P πŸͺ¦) and EsLint have rules that you can enable to make sure nothing gets merged that imports modules without using them. Make sure you serve the minimum amount of code necessary.

Solution

There are three parts to the solution:

  1. Setup Prettier
  2. Setup Prettier Import Order Plugin
  3. Do work

Part 1 - Setup Prettier

Right now, our imports look something like this:

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { EventLoggingService, EventType} from 'business-logic';
import { ActivatedRoute, Router } from '@angular/router';
import { BehaviorSubject, zip } from 'rxjs';
import { fadeInOutTrigger, fadeInTrigger } from '@shared/animations/animations';
import { filter, map, tap, withLatestFrom } from 'rxjs/operators';
import { SearchPopupService } from '../search-popup.service';
import { HomePageReview } from '../home-core/data/homepage-data';
import { DateTimeRangeInputStyles } from '@shared/date-time-range-input/date-time-range-input-styles';

Nothing wrong with this, but we can do better. We can enable our IDE to at least order imports automatically. After we do that, they look just a tad better.

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { fadeInOutTrigger, fadeInTrigger } from '@shared/animations/animations';
import { DateTimeRangeInputStyles } from '@shared/date-time-range-input/date-time-range-input-styles';
import { EventLoggingService, EventType} from 'business-logic';
import { BehaviorSubject, zip } from 'rxjs';
import { filter, map, tap, withLatestFrom } from 'rxjs/operators';
import { HomePageReview } from '../home-core/data/homepage-data';
import { SearchPopupService } from '../search-popup.service';

Now that the settings are correct, let's install Prettier: npm install --save-dev prettier. We want to use save-dev because we only need it for development.

Now, for what it's worth, this is my usual .prettierrc.js file.

module.exports = {
semi: true,
trailingComma: 'none',
singleQuote: true,
printWidth: 100,
tabWidth: 2,
endOfLine: 'lf',
bracketSpacing: true,
bracketSameLine: true
};

This is where developers spend eons arguing what's best. I don't care that much as long as it's consistent across the whole team.

Part 2 - Setup Prettier plugins

Now, this is where the magic πŸ§™β€β™‚οΈ comes in. Thanks to people at Trivago, we have this plugin available to us: prettier-plugin-sort-imports. Just install it with npm install --save-dev @trivago/prettier-plugin-sort-imports;

You can find more options in the documentation, but this is my goto:

module.exports = {
semi: true,
trailingComma: 'none',
singleQuote: true,
printWidth: 100,
tabWidth: 2,
endOfLine: 'lf',
bracketSpacing: true,
bracketSameLine: true,
importOrder: [
// Place angular import at the top
'^@angular$',
'rxjs',
// External dependencies
'^\\w',
// This project's own aliases
'^(@shared|@core|@env|@test-utilities)(/.*|$)',
// This project's extra libraries
'^(business-logic|@ui)(/.*|$)',
// Every import starting with ./ or ~/
'^[./|~/]'
],
importOrderSeparation: true,
importOrderParserPlugins: ['decorators-legacy', 'typescript']
};

You'll notice that I added 3 more options for import, importOrderSeparation and importOrderParserPlugins. This is tailored for an Angular project, but you can easily tailor it to anything.

Now, assuming you have the prettify-my-code-on-save option enabled in your IDE, if you do a quick Cmd + S, your imports should look like this:

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { BehaviorSubject, zip } from 'rxjs';
import { filter, map, tap, withLatestFrom } from 'rxjs/operators';

import { EventLoggingService, EventType} from 'business-logic';

import { fadeInOutTrigger, fadeInTrigger } from '@shared/animations/animations';
import { DateTimeRangeInputStyles } from '@shared/date-time-range-input/date-time-range-input-styles';

import { SearchPopupService } from '../search-popup.service';
import { HomePageReview } from '../home-core/data/homepage-data';

To me, this is so much Prettier(pun intended πŸ₯). Imports are grouped into categories defined by me, and they get a nice empty line in between categories. Sweet!

Part 3 - Do Work

Again, this is highly subjective. Please customise it however you want. In the end, it's just a tool. πŸ› 

Want more?

If you want to know more about this, or something doesn't make any sense, please let me know.

Also, if you have questions, you know where to find me… On the internet!

Be kind to each other! 🧑

Over and out

My Twitter avatar
Catalin Ciubotaru πŸš€

New blog post ✍️ => Organise imports with Prettier and friends https://catalincodes.com/posts/organise-imports-with-prettier-and-friends #Prettier #Typescript

Jun 26, 2022
36 people are talking about this

Wanna read more?

Updates delivered to your inbox!

A periodic update about my life, recent blog posts, how-tos, and discoveries.

No spam - unsubscribe at any time!