DEV Community

loading...
Cover image for NextJS Tip: Relative ES6 Modules

NextJS Tip: Relative ES6 Modules

whoisryosuke profile image Ryosuke Originally published at whoisryosuke.com ・2 min read

Do your components look like this in NextJS?

import ShopProfile from '../../layouts/ShopProfile/ShopProfile'
import KushyApi from '../../utils/KushyApi'
import Menu from '../../components/Menu/Menu'
Enter fullscreen mode Exit fullscreen mode

This kind of setup is ok for smaller projects, but the second you need to shift a component around folders, it's easy to get lost in a sea of relative directories (was it two or three sets of .../ 🤔).

The plugin way

The babel plugin called root-import can handle this for us, and it's pretty easy to setup:

npm install babel-plugin-root-import --save-dev

Add a .babelrc to your project root:

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        [
            "babel-plugin-root-import"
        ]
    ],
    "env": { // For React Native
        "production": {
            "plugins": [
                "babel-plugin-root-import"
            ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it. You can include components by using the ~ symbol as the root path:

import ShopProfile from '~/layouts/ShopProfile/ShopProfile'
import KushyApi from '~/utils/KushyApi'
import Menu from '~/components/Menu/Menu'
Enter fullscreen mode Exit fullscreen mode

Since NextJS uses a custom babel setup, when we provide our own setup, it overrides the default config. Which means we lose all kinds of great functionality, like object spread. That's why we use Next's Babel presets in the beginning of the config("presets": [ "next/babel" ],), and drop our plugin underneath. Now you shouldn't get any errors during compilation.

The better way

I looked up how to do this in general, not specifically for NexJS, and I found a site with a pretty concise guide. It stated that for Webpack 2, you'd add this to your webpack.config.js:

resolve: {
  modules: [
    path.resolve('./')
  ]
},
Enter fullscreen mode Exit fullscreen mode

So in NextJS, I tried doing this:

const withLess = require('@zeit/next-less')
const withCSS = require('@zeit/next-css')
const path = require('path')

// To add new modules, nest the function (like a HOC in React)
module.exports = withCSS(withLess({
    webpack(config, options) {
        config.module.rules.push({
            test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
            use: {
                loader: 'url-loader',
                options: {
                    limit: 100000
                }
            }
        })

        // Here is the magic
        // We push our config into the resolve.modules array
        config.resolve.modules.push(path.resolve('./'))

        return config
    }
}))
Enter fullscreen mode Exit fullscreen mode

This allows you to use your components and modules like this:

import ShopProfile from 'layouts/ShopProfile/ShopProfile'
import KushyApi from 'utils/KushyApi'
import Menu from 'components/Menu/Menu'
Enter fullscreen mode Exit fullscreen mode

A bit cleaner than using the ~ symbol, way easier than installing another dependency 👍

Hope that helps 🍻
Ryo


References:

Discussion (0)

pic
Editor guide