Hem
Nyheter
Kod

Skrivet av David Utegård

Absoluta importer med module path alias

2022-07-21Utveckling

När du importerar en resurs från en annan plats i ditt projekt kan du välja att arbeta med relativa eller absoluta sökvägar. Av egen erfarenhet är relativa sökvägar den överlägset mest använda metoden för att hantera import, men när projekt växer i storlek och mappstrukturer blir mer komplexa leder de relativa sökvägarna till en oändlig mängd '../' och det kan bli svårt att hitta resursen.

Absolut vs Relativ

Absoluta sökvägar kommer alltid att inkludera hela kataloglistan från projektets rot till filen, till exempel /src/foo/bar/shared.

Relativa sökvägar å andra sidan kommer alltid att betrakta den aktuella filen som root i förhållande till de resurser som den importerar. Att använda relativa sökvägar gör så att samma resurs kommer att ha olika importsökvägar beroende på var de importerade filerna finns.

Om vi till exempel vill importera något från /src/foo/shared i /src/bar/ skulle sökvägen vara ../foo/shared men för /src/bar/relative skulle sökvägen istället vara ../../ foo/delad.

Konfigurerade absoluta importer i TypeScript

Både absoluta och relativa vägar har sina för- och nackdelar när de används för import, men i TypeScript kan vi förkasta de två tidigare alternativen och istället välja ett tredje alternativ som med små konfigurationer kommer att hantera importer på ett sätt som kommer att rensa upp dina importer och göra det mycket lättare att läsa, tolka och hitta den importerade resursen.

Med bara några enkla konfigurationer i din tsconfig.json kan vi gå från detta:

import ForbiddenError from '../../../errors/Forbidden'
import InvalidEntityError from '../../../errors/InvalidEntity'
import NotFoundError from '../../../errors/NotFound'
import { getPostById } from '../../../repository/post'
import { getUserById } from '../../../repository/user'
import { createLike } from '../../../repository/like'
import { generateError, generateSuccess } from '../../shared/responseHelper'

Till detta:

import ForbiddenError from '@errors/Forbidden'
import InvalidEntityError from '@errors/InvalidEntity'
import NotFoundError from '@errors/NotFound'
import { getPostById } from '@repository/post'
import { getUserById } from '@repository/user'
import { createLike } from '@repository/like'
import { generateError, generateSuccess } from '@shared/responseHelper'

Hur du konfigurerar ditt projekt

I din tsconfig.json lägg bara till roten som baseUrl och önskade sökvägar till compilerOptions-objektet och du är klar.

"baseUrl": ".",
"paths": {
  "@helpers/*": [
    "src/helpers/*"
  ],
  "@errors/*": [
    "src/errors/*"
  ],
  "@types/*": [
    "src/types/*"
  ],
  "@repository/*": [
    "src/repository/*"
  ],
  "@shared/*": [
    "src/functions/shared/*"
  ],
  "@middleware/*": [
    "src/functions/middleware/*"
  ]
}

Beroende på vilken kompilator eller modulbundler du använder kan det tolka importerna som paket och försöka hitta en node_modules inuti mapparna och när den saknas kommer kompileringen att gå sönder.

I detta projekt använder vi webpack som modulbundler och tolkningsproblemet kan lösas ganska enkelt genom att lägga till namn och sökväg som alias i webpack.config.js

module.exports = {
  resolve: {
    extensions: ['.js', '.ts', '.graphql', '.gql'],
    alias: {
      '@helpers': path.resolve(__dirname, 'src/helpers'),
      '@errors': path.resolve(__dirname, 'src/errors'),
      '@types': path.resolve(__dirname, 'src/types'),
      '@repository': path.resolve(__dirname, 'src/repository'),
      '@shared': path.resolve(__dirname, 'src/functions/shared'),
      '@middleware': path.resolve(__dirname, 'src/functions/middleware'),
      '@': resolve('/src')
    }
  }
}