19
Improving the Next.js config
For the past few years I have been an avid lover of Vue.js and in the past year or so been using it in combination with Vite, an all new build tool that is just out of this world fast β‘.
However, spending more time working in the industry I have learned to fall back in love with React and more specifically Next.js.
However, since switching back to using Next.js after so many years, I have noticed a number of things that have made me want to go back to using Vue + Vite.
As the title implies, this post is going to focus specifically on how to improve the Next.js config by focusing on a handful of the top/best config options used in other build tools like Vite.
In general I feel like there should be more options added to the config file. Looking at the shared options in Vite, here are just a few that would make a lot of sense to add:
-
build
: Customize the build outputOffer more customization for the build configuration of your project. In the case of Next.js I feel a lot of existing build options could be moved here. EG:
swcMinify
,webpack
, etc. -
define
: Define global constant replacementsAs a good alternative to having to add
NEXT_PUBLIC_
environment variables all the time you can use this to define public constant variables. logLevel
: Adjust console output verbosity-
plugins
: Array of plugins to usePlugins are a big feature that I'm going to dive into more later.
-
root
: Project root directoryRe-learning Next.js over the past few months I have been researching a number of open source projects, many of which like to point to a custom root directory. Most commonly a
src/
directory. -
server
: Server optionsCustomize the server configuration with options like
cors
,port
, etc.
The majority of these options simply add project structure flexability & extensibility for more advanced users.
Moving onto what is, to me at least, one of the most obvious features. TypeScript support.
I personally don't like using the CommonJS syntax where possible. To the point that for most projects now when I want to write a simple Node script I quickly add tsup
so I can use TypeScript & a number of other handy features.
One scenario I particularly hate is when a library offers a object type definition & but you have to use the JSDoc @type {import('...').TypeName}
syntax to use it.
For comparison: This, to me, is ugly:
// next.config.js
/**
* @type {import('next').NextConfig}
*/
module.exports = {
// ...
}
This however, looks much cleaner:
// next.config.ts
import type { NextConfig } from "next";
export default {
// ...
} as NextConfig;
No, type safety isn't needed for a config file. But when writing it it can be very helpful to have tools, such as intellisense, to help prompt any issues with your setup or help save you from having to even look up the conig documentation.
next.config.ts
has been talked about for 3 years now & has still not been added. This issue has been tracking this request since first posted in 2018 and still to this day has people asking for it.
I can very much understand if there are more pressing features, bugs, etc that need to be addressed. But Next.js 12 has just been released, the Next.js core has been running on TypeScript since 2019 & Vercel has constantly preached how amazing TypeScript is to the point it works out of the box pretty much.
And yet, the Next.js config still only allows a CommonJS JavaScript file.
One of the second features that I think would have the biggest & best impact on Next.js would be an all new plugins system.
Currently Next.js does provide a plugin system of sorts but is, as far as I can tell, community made & managed by nesting functions that return an updated Next.js configuration object. Not so pretty.
In an indeal world an all new plugins system could make it even easier to bootstap & customize a Next.js project with your favourite tools in a matter of minutes, not hours like it does today.
Imagine if you could add TailwindCSS to your Next.js project by just doing this:
npm install --save-dev next-plugin-tailwindcss
# Or with Yarn
yarn add -D next-plugin-tailwindcss
// next.config.js
/**
* @type {import('next').NextConfig}
*/
module.exports = {
plugins: [
require("next-plugin-tailwindcss")(),
]
}
That's basically how Vite's plugin system works & how nice & easy it is to work with. It has a plugins
property that allows you to simply provide an array of plugin methods that you call with your desired options.
This system has become so popular that there are a huge number of plugins to let you to almost anything and everything you could need. Here is a few examples of my favourites:
-
vite-plugin-icons
: Access thousands of icons via Iconify. -
vite-plugin-markdown
: Import markdown files content, frontmatter, etc. -
vite-plugin-pwa
: Generate all assets needed to make your app PWA ready. -
vite-plugin-windicss
: Quickly add WindiCSS (TailwindCSS + some cool extras).
With all of those features all put together you end up with something that looks a little like this:
// next.config.ts
import TailwindCSS from 'next-plugin-windicss';
import type { NextConfig } from "next";
export default {
build: {
swc: {
minify: true,
},
webpack: (config, { dev, isServer }) => {
// ...
},
},
experimental: {
// ...
},
images: {
// ...
},
plugins: [
TailwindCSS(),
],
root: "./src/",
server: {
headers: [
// ...
],
port: 4000,
},
} as NextConfig;
One argunment I could see for NOT to make all these big, possibly breaking, changes to the config system would be "But Next.js is so simple to use. This will just add complexity".
Fair point. But if done correctly it could be backwards compatible with the current config system & then allows more experienced developers who do want to utilize some of the new features, such as plugins, TypeScript support, etc, can do so.
Of course all of this is just my opinion on how to improve the Next.js config system & how I think it should look, but others may have differing opinions / preferences, which I am very open to discussing.
For now though I feel like this needs to be something that should be discussed more in the community & looked into further as it could very much make Next.js even more powerful than it already is.
19