Next.js: next.config.ts

Created on 28 Sep 2018  ·  20Comments  ·  Source: vercel/next.js

Feature request

Is it possible to use next.config.ts instead of next.config.js?
Currently none of the typescript examples use typescript in the config file. Is it even possible?

@resir014

Most helpful comment

any changes here since nextJs Core is running with typescript?

All 20 comments

If you want to do something like this it's your own responsibility to compile next.config.ts to next.config.js. We're not planning to transpile next.config.js.

@virzak Yeah, not without much effort. It will require runtime transpilation w/ ts-node, and it adds unnecessary complexity to Next.js.

You can however, use // @ts-check to type check your next.config.js just like you would in Flowtype.

any changes here since nextJs Core is running with typescript?

Any chance this issue could be reconsidered? It was closed over a year ago and a lot has changed since then, TS support is now part of the core.

A specific reason I would like to have next.config.ts is because I want to set publicRuntimeConfig: { appInfo: generateAppInfo() }. The generateAppInfo() function sits in helpers.ts and returns a data structure that is type-checked against the AppInfo interface. The contents include enabled feature switches, git commit hash, sentry id and other things a launched app instance would need.

The same generateAppInfo() function is used in Jest mocks, so moving its implementation out of a ts file right into next.config.js would not be possible. Seems like I now need to extract generateAppInfo() into a separate js file, thus losing type checking against AppInfo interface 🤔

Still the same as https://github.com/zeit/next.js/issues/5318#issuecomment-425398180

Compiling it would slow down bootup and make config loading significantly more complex compared to the benefits.

I believe the main performance problem is production-related. What if next.config.ts was compiled into .next directory along with other code, which would remove a need to pass it via babel or ts-node in production? Boot time should remain the same if not slightly better given that there will be scope for build-time optimisations.

It's both development and production. Note that this file is a config file and generally shouldn't have anything complex in there.

It should just build and cache the config like everything else so it doesn't slow bootup performance. Plus, I would be shocked if it was a significant performance impact on bootup compared to the benefits. It's frustrating not being able to use a consistent language throughout my entire project and include the same linting tools or esnext syntax.

Note that this file is a config file and generally shouldn't have anything complex in there.

Umm, maybe for super simple use cases? I don't know. I work on big complex apps that require a lot of customization and tweaking. Data on this would be interesting. They certainly felt it was worthwhile to transpile preact.config.js and I haven't seen any noticeable performance issues with that. Not sure why this would be any different.

One particularly useful tool for modifying configs imperatively like this that loses a lot of benefits without transpiling TS is Ramda. That's my FP toolbelt for everything because it has awesome TS support for dynamic type inference when currying.

Is supporting a transpiled next.config.ts still not being considered? Our specific use case is simply that we have multiple functions a services directory that are fully typed. The services consume our APIs and are fully typed. Currently we have to duplicate the service, one typed and one untyped, since we also need them to consume our APIs and generate our exportPathMap.

Generating a list of urls to export will be covered by getStaticPaths in #9524

You probably already have the following 2 packages installed if you are using typescript with nextjs:
@babel/core
@babel/preset-typescript

Then you can use a function like the one below to require typescript file on the fly:

function requireTypescript(path) {
  const fileContent = require('fs').readFileSync(path, 'utf8')
  const compiled = require('@babel/core').transform(
    fileContent,
    {
      filename: path,
      presets: [ '@babel/preset-typescript' ],
    },
  )
  return eval(compiled.code)
}

Then use it in your next.config.js like this:

const myModule = requireTypescript('./path/to/mymodule.ts')

_Note: you will need to inject some path information if your ts file is not in the same folder of next.config.js and you have relative import inside the ts file you are requiring. So, keep the target ts file simple._

Note about https://github.com/zeit/next.js/issues/5318#issuecomment-575959060

  • Slows down bootup when using next start
  • Slows down bootup in development

But if you decided to use typescript in your project, didn't you already trade in some performance for type safety? How come the performance impact is not seen as problematic when it happens on every change of a file, but is suddenly so insurmountable when it's once on boot? And If you cache it a bit smart it's not even happening on every boot.

If the concern is that people would blame next.js for slow bootup instead of typescript, maybe a log could be added like

> compiled next.config.ts (1700ms)

That would make clear to people which impact the use of which tool has for them.

@Janpot because it's cached inside Next.js and not with this method. On top of that it affects production boot if you use next start, as it loads next.config.js. Next.js doesn't compile typescript on production boot.

Yes, I agree, not with this method. But if next were to hypothetically implement this feature, I presume it wouldn't be too hard to add cache. Since next.js already has infrastructure to compile and cache typescript. And for production boot it could precompile when running next build? All of that would make the performance impact very minimal.

I used typescript ever since it's supported in nextjs and was thinking that it could be cool that next.config.js to be next.config.ts. But aside type checking, I never needed config to be a typescript file, so this issue didn't bother me too much. But now I wanted to import a ts helper script in my next.config.js (to generate paths for exportPathMap), which is used in several places, but turns out I can't use ts here (obviously..?). So now I'm concerning again that next.config.js should be actually next.config.ts, so ts imports supported too, so I came here...

I see the workaround suggested by @lsm here, but this requires some overwhelming customization with babel etc just for this one file??

Either babel, or a separate tsconfig and some script running tsc to emit js, so I could import this helper file as js. Which isn't any better...

But then I see that author doesn't want to add support for "just this one file" too, and I'm starting to see some irony.

🤔🤔🤔🤔🤔🤦‍♂️

P.S. I don't know what I'll do with all this yet, but wanted to at least share my feelings
P.P.S. I've seen getStaticPaths but it's not the same as exportPathMap, I need path mapping

UPD. on a second glance, @babel/core and @babel/preset-typescript are already part of nextjs, so I tried the code suggested by @lsm but I'm getting SyntaxError: Cannot use import statement outside a module

UPD2. ok, I gave up: I changed this ts helper script to js, and required/imported it where I needed (in next.config.js, and in a page, used it in getStaticProps since it uses fs lib)

@JerryGreen Would moving that useful helper as TS into an npm package that publishes as JS have been an option for you?

I've got the same issue as @JerryGreen. Was considering making the code an npm package, but there's too much that will be project-specific so I'd need to publish a new package for each project. I'll have to give up on this for now and just duplicate some of this code in js.

However, a better solution to my use case would be to have the option to run scripts during the build cycle, similar to how Gatsby does it in gatsby-node.ts.

@dpwolfe yeah, I agree with @beppek, this thing appears to be a bit too project specific. In my case I have files in pages folder that start with a date (shorten timestamp), something like 20200917-hello-world, and I want it to be accessible via /hello-world path. So I had to write function that goes through file system, applies regular expression, and generates required paths for exportPathMap, creating an object consisting of entries like /blog/posts/20200917-hello-world, -> /hello-world. Seems to be too project specific, so I don't see actual reasons to publish it into a package. Btw I kinda lied about getStaticProps - it turned out I don't need that. Custom exportPathMap is enough for that need. Still, weird that this helper had to be written in js, because if I write it in ts, then I wouldn't be able to import it from next.config.js... I probably should indeed move this helper into a separate package, write it in ts, yet compile it into js, so it will be possible to use it within next.config.js but just for personal need, barely anyone would need that.

I am running into eslint errors that need to be suppressed like this

/* eslint-disable @typescript-eslint/no-var-requires */
const withFonts = require('next-fonts');

This should be reopened or at least something added to the typescript documentation to mention that this is a known issue. It would add polish to document this upfront or even better allow next.config.ts.

Was this page helpful?
0 / 5 - 0 ratings