Next.js: [RFC] `src` directory

Created on 20 Aug 2019  ·  32Comments  ·  Source: vercel/next.js

This is now supported in the latest versions of Next.js!

Goals

  • Allow users to have their pages in src/pages

Background

Next.js has a special pages directory where every file becomes a separate route, following the convention over configuration approach this directory is required to be in the root of a Next.js application.

Over time there's been multiple issues asking for a configuration option to change pages to something else, generally with the argument of "I want to change it". However, over time in talking with users I've established a common pattern that what is generally the actual question is "I want to put my code in a src folder, how can I do that?".

When looking at various closed source codebases it was quite common to see next dev ./src or next build ./src to handle having pages in the src directory.

However in doing so you move the Next.js root to src instead of the main directory of the app, meaning that compilation (like Babel) won't be applied to files outside of src.

On top of this Next.js creates tsconfig.json and next-env.d.ts in the Next.js root, as the Next.js root is where your app lives.

There's a few reference issues #4789, #8415, #4315, #3921, #5303, #2202, #3416

Proposal

Add support for src to hold pages. There can only be one pages directory, so the user either has ./src/pages or ./pages, having both would throw an error. public (experimental) and static would still exist next to the src directory, so they wouldn't be inside of src. This would be similar to the Create React App enforced directory structure.

Most helpful comment

I am disappointed by the fact that people prefer strictly the convention over configuration, whereas I think for good open source project there should be balance between convention and configuration.

I have seen people requesting support for custom pages directory for long. It would have been better have a next.config.js to have pagesDir config support.
I struggled to use nextjs with electron, tried electron-next as well as nextron, in both cases it failed to work with non-ssr compatible module just because of the pages directory, I remember when I moved this to root from renderer sub folder, it worked (with dynamic import and ssr: false).

similar thing is with disabling ssr on one page out of many, I would not want to switch to different ssr or static exporter like Gatsby or anything else just for facing issue with one page. in my case the dynamic workaround would be to load entire page as component as dynamic import and essentially the ssr processing is wasted.

NextJs as very good convention for working with React and I would love to use it, probably I have to maintain a fork if I like this more in future. Having balanced approach would be much better IMO.

I will still be using nextjs, not going to stop over few disappointments anyways.

All 32 comments

I'd love to see api folder inside src also. The problem is user might use different programming languages for api as zeit allows multiple builders.

The api directory is already inside of pages/api, so it'll be in src/pages/api.

I’d prefer if it was completely customizable. In my case I have a monorepo using yarn workspaces and I’d like for the pages directory to be inside my packages/landing, not the root of the monorepo.

That would be great! For instance, when running CLIs like eslint I often do eslint ./src. At the moment, I needed special handling for the pages directory. This proposal would fix this.

@brunolemos in that case your project structure seems off, Next.js should be installed and booted inside packages/landing.

I really like this approach as well, I feel like it will produce a more navigatable structure for new comers. Something to the effect of /server has all the custom server things and /src has the app specific code :) Great work @timneutkens I absolutely love this tool!

in that case your project structure seems off, Next.js should be installed and booted inside packages/landing.

Then I would lose the monorepo benefits, since I use code from packages/core inside my packages/landing. But ok, I can move Next.js to packages/landing and install packages/core from npm instead (or leave it as is, since it works).

@brunocascio you can use https://github.com/martpie/next-transpile-module to transpile core module.

Cool that this is coming! Is this about src only or will it be configurable? (For us, src is the name we use but I've been on the wrong side of the "convention over configuration" before 😄.)

This is awesome. Thank you @timneutkens. I think just covering src/pages will already fix the majority of "issues".

@borekb It won't be configurable, as this covers the majority use case 👍 And allowing this to be configurable could cause misuse.

This is a major improvement, for sure; however:

This would be similar to the Create React App enforced directory structure.

Create-React-App allows for the developer to eject the app from its defaults. Following this line, I haven't heard a compelling argument why an unrestricted config option (where pages can be whatever you want) is off the table. There are plenty of ways a developer can misconfigure next if they so want, why draw the line here?

@SirensOfTitan i haven't heard a good argument to allow it, and by allowing it you open up a can of worms of weird use-cases that break in many ways, we've seen this happen with distDir many times and has caused quite a maintenance burden on our side (and developer frustration when things don't work as expected). The way it is currently we can guarantee things work through integration tests and continue to work correctly in the future.

Time to move back to next when this is ready, cheer

@jeremy-coleman I don't see how this relate to the RFC.

That is already the case. pages get compiled into .next.

There's no reason for doing so at this point.

That's not something we're pursuing and unrelated to this RFC.

I just started picking up Next, and I'm quite surprised that this issue is only 10 days old. I'd like to give some feedback, in case it might be useful:

  • I've explored the issue tracker a bit, and I think you guys are closing issues too aggressively, there shouldn't be a 10 days old issue about this, there should have been an issue about this somebody started years ago, where even if there was no plan to implement this at that time people could have still upvoted it via ":+1:"s.

  • It's great that Next is opinionated, up until the moment when I want to do something and I either simply can't do it or I have to jump through multiple unnecessary hoops to do it, just because somebody in the core team don't like my use case. Being opinionated is good, but flexibility is also good.

@fabiospampinato

I've explored the issue tracker a bit, and I think you guys are closing issues too aggressively,

I disagree. We reply on basically all issues, even closed ones. The ones that we do close are related to either not following the issue template (questions) or things that we won't pursue anytime in the future. You can still use 👍 on closed issues and we regularly check that to course correct the roadmap if needed. This particular RFC is one of such. For reference we get hundreds of GitHub notifications per day and both me and @Timer are going through them all multiple times per day.

there shouldn't be a 10 days old issue about this, there should have been an issue about this somebody started years ago, where even if there was no plan to implement this at that time people could have still upvoted it via "👍"s.

If we take this approach there would be a multitude of non-actionable open GitHub issues, making it unmanageable to find actionable ones and to prioritize those.

It's great that Next is opinionated, up until the moment when I want to do something and I either simply can't do it or I have to jump through multiple unnecessary hoops to do it, just because somebody in the core team don't like my use case. Being opinionated is good, but flexibility is also good.

The main goal for Next.js is to have the right defaults for building websites / web applications and giving flexibility between tradeoffs (eg static, ssr, etc) while putting you / your team into the pit of success. I recently did an interview that covered this a bit: https://infoq.com/news/2019/08/nextjs9-interview-neutkens/

I want to do something and I either simply can't do it or I have to jump through multiple unnecessary hoops to do it, just because somebody in the core team don't like my use case.

We're always happy to take feedback! 🙏 Feel free to reach out to me directly or create a feature request issue.

@timneutkens

The ones that we do close are related to either not following the issue template (questions) or things that we won't pursue anytime in the future.

Here there's a ~15 months old issue for basically the same thing we are discussing here, it seems the issue template has been used and it was closed because that wasn't a feature you guys wanted to work on, still here we have an RFC about basically the same thing.

My point is that by keeping more issues open you'll both get a better understanding of what your users want and you'll give them a way to express their support for the issues they care about by using reactions.

You can still use 👍 on closed issues

Sure but how many people do that, I personally don't do it because if an issue has been closed it seems pointless to me to add my ":+1:" to it.

If we take this approach there would be a multitude of non-actionable open GitHub issues, making it unmanageable to find actionable ones and to prioritize those.

I can see this becoming a problem. However those issues could be tagged with a special label, like "maybe" or something like that, and then they can be filtered out from the search results via "-label:maybe", at the same time it'll be possible to sort these issues by number of reactions, I think it's possible that issues such as the one discussed here would have become actionable sooner if there were hundreds of ":+1:" to it.

Anyway I think Next (and zeit in general) is awesome and you guys are doing great work!

Here there's a ~15 months old issue for basically the same thing we are discussing here, it seems the issue template has been used and it was closed because that wasn't a feature you guys wanted to work on, still here we have an RFC about basically the same thing.

It is not the same thing, as outlined in the background of this RFC:

Over time there's been multiple issues asking for a configuration option to change pages to something else, generally with the argument of "I want to change it". However, over time in talking with users I've established a common pattern that what is generally the actual question is "I want to put my code in a src folder, how can I do that?".

pagesDir is not something we ever planned on implementing, hence why it was closed. Maybe we should have engaged more and asked "what problem are you trying to solve" though. This is something that has changed in how we manage the project though, this issue is incredibly old.

Hi I'm just inserting one argument for why it would be nice to have the option to change the name of /pages (or other convention naming)

I like to organise all React code in folders prefixed with @, just to have them sorted to the top in alphabetical order.

It'll look like

/@dumb
/@pages
/@smart
/@icons
/api
/data
/hooks
...

One less braincell to figure out where to look for files, I'll take it ✋

Yep, I came here looking for any gotchas about putting /pages and other directories I use to organize my project (e.g. /components, /middleware, /utils) inside of a /src directory and simply changing the next scripts to target ./src.

I prefer my projects organized this way because it's the convention I've always followed — configs, /src, /dist all in the project root. It feels less cluttered when I'm navigating through the project via IDE or terminal.

But as @timneutkens mentioned the below complications, I'll wait until it's officially supported.

However in doing so you move the Next.js root to src instead of the main directory of the app, meaning that compilation (like Babel) won't be applied to files outside of src.

On top of this Next.js creates tsconfig.json and next-env.d.ts in the Next.js root, as the Next.js root is where your app lives.

@timneutkens couple things, more of an fyi than anything. Currently I'm using typescript with my next proj in /src. Next recreates next-env.d.ts as you mentioned which is a non issue, but next wants to of course create a new tsconfig and complains if missing. So what I did for the moment is just create an empty tsconfig.json and then extend from the root tsconfig.json. Then just tell next to use src dir. Works just fine.

That all said defaulting next to the src dir is likely a good idea. It's the most common convention and widely used. As much as some of the other flexibility mentioned above would be "nice to have" I wouldn't suggest it. Too much of a support nightmare. Moving to src dir will solve the vast majority of devs.

@timneutkens

Maybe we should have engaged more and asked "what problem are you trying to solve" though.

Specifically, my 'problem' is that I have a complex dev environment that is common to many apps. I would like to maintain the environment and the app separately.

To elaborate on what @blujedis said about src being a common convention:

While I haven't gotten around to it yet, I hope to package Next and my common dev environment separately from the the actual app. In this way I would have only one set of 'dev environment' maintenance tasks covering a multitude of apps. Each app would include only the code specific to the app and not to the environment.

Here's the root dir of one of many apps I'm working on. Everything you see here, with the exception of src belongs to the environment. The app is contained entirely in src.

This, IMO, is a logical extension of the idea Next is built on.

image

@gihrig have nearly the identical structure FWIW right down to the config dir...

We can we see this feature landed :)

I am sure we would want to add renderer/pages to this list as electron with nexjs usually have pages inside renderer folder. much needed as using non-default pages dir breaks the dynamic import with ssr: false

I am disappointed by the fact that people prefer strictly the convention over configuration, whereas I think for good open source project there should be balance between convention and configuration.

I have seen people requesting support for custom pages directory for long. It would have been better have a next.config.js to have pagesDir config support.
I struggled to use nextjs with electron, tried electron-next as well as nextron, in both cases it failed to work with non-ssr compatible module just because of the pages directory, I remember when I moved this to root from renderer sub folder, it worked (with dynamic import and ssr: false).

similar thing is with disabling ssr on one page out of many, I would not want to switch to different ssr or static exporter like Gatsby or anything else just for facing issue with one page. in my case the dynamic workaround would be to load entire page as component as dynamic import and essentially the ssr processing is wasted.

NextJs as very good convention for working with React and I would love to use it, probably I have to maintain a fork if I like this more in future. Having balanced approach would be much better IMO.

I will still be using nextjs, not going to stop over few disappointments anyways.

I think preventing a config option that's well documented because similar options were misused (BTW I personally think they were misused due to poor documentation and because the proper config options wasn't available like the pages directory)

My use case which I don't see discussed or see a feasible alternative to is to use use a next app as several apps that share components and build processes. I'd love for a different pages directory for the "admin" portion of my app that reuses many of the same components as my website. I've tried sharing components but the restrictions with webpack building node modules with nextjs has made this very frustrating. A simple pagesDir would save people so many headaches and allow for nextjs to scale beyond a starter app.

Why not label the config option to dangerouslyChangingPagesDir and document is clearly?

Was this page helpful?
0 / 5 - 0 ratings