Better Next.js Imports

Nine days after first writing this post, the Next.js team landed support for paths in tsconfig.json and jsconfig.json by default! In Next.js 9.4 and onwards, you only need to specify a baseURL in your config file to support absolute imports:

// tsconfig.json or jsconfig.json
{
"compilerOptions": {
"baseURL": "."
}
}
// import Button from 'components/button'

To use a custom prefix, add a paths configuration:

{
"compilerOptions": {
"baseURL": ".",
"paths": {
"@components/*": ["components/*"]
}
}
}
// import Button from '@components/button'

Editors like VSCode automatically support the config in jsconfig.json, so Command+Click to jump to the source of a file will work as usual. Atom and IntelliJ also have support for rewrites.


The original post, using a babel plugin.

Relative import statements are a pain. To avoid ../ chains, improve code portability, and type less, I've started using babel-plugin-module-resolver in my Next.js projects.

The goal is to transform verbose import statements like this:

import Button from '../../../../components/button'

into absolute import statements that work anywhere in your project:

import Button from '@components/button'

Let's do it. Install the babel plugin as a devDependency:

$ yarn add babel-plugin-module-resolver -D

In the root of your Next.js project, create a .babelrc.json file and add the module-resolver plugin:

module.exports = {
presets: ['next/babel'],
plugins: [
[
'module-resolver',
{
alias: {
'@components': './components',
},
},
],
],
}

Create a jsconfig.json (or tsconfig.json if you're using TypeScript) and add the paths property:

{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["components/*"]
}
}
}

Note that the syntax is slightly different than the babel config.

If you're using a mixed JS/TS codebase, you should include JS files in your tsconfig.json:

{
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"]
}

Now you can update your import statements to use the new syntax!