Next.js: How to change where Next looks for pages?

Created on 17 Jul 2018  ·  32Comments  ·  Source: vercel/next.js

Every .js file in pages becomes a route, can i change it?

I want use src/pages

Most helpful comment

No idea what these other comments are saying but you can configure which directory next.js looks for pages from the command-line:

$ next ./src
$ next dev ./src
$ next build ./src
$ next start ./src -p 8080

All 32 comments

According to docs, dir specifies the location of the project, so the correct way would be to set it to ./src:

const next = require('next')({
  dev,
  dir: './src'
})

But it's only used in a programmatic API (with a custom server) and will affect the presumed location of other files as well (like next.config.js and static directory, I believe).

No idea what these other comments are saying but you can configure which directory next.js looks for pages from the command-line:

$ next ./src
$ next dev ./src
$ next build ./src
$ next start ./src -p 8080

You can't change the directory, and we're not planning to change this, please search for an issue on the issue tracker (including closed issues) in the future before posting an issue, as this question has come up quite a few times.

@timneutkens don't be like maintainer of moment.js, who rejected optimization for client-side apps, what is led to custom configs in a lot of projects, even in CRA.
A lot of project boilerplates has an src folder, where files lay.

As this is currently the first result on google when searching for this, maybe it would be beneficial to explain the reasoning behind that decision @timneutkens ?

As stated by @brainkim jus append your package json scripts with ./src. What you also might want to do is configure the next dist folder (I wanted dist in root).

Note that we prepend the folder with ../.

// src/next.config.js
module.exports = {
  distDir: '../dist'
}
// package.json
  "scripts": {
    "dev": "next ./src",
    "build": "next build ./src",
    "start": "next start ./src",
    ..
  },

@msegers I'm trying to follow this setup and getting tons of errors like this:

Cannot find module 'next/document'
Cannot find module 'next/error'
...

on HTTP request (no errors at the import phase). Any idea how to fix that?

The requirement of having pages at root really drives me nuts – for anything realistically big, things start to pile up at the root uncontrollably: styles, components, client store, config files, etc. Wish there were a workaround.

Addition: tried to symlink pages to client/pages. Most of the stuff seems working, except Hot Reload. Sad :(

@msegers Suggestion worked for me.

If you use next-i18next make sure you set the correct localePath in the NextI18 config:localePath: 'src/static/locales/',

Like this :

NextI18NextInstance = new NextI18Next({
  defaultLanguage: 'en',
  otherLanguages: ['en'],
  debug: true,
  localePath: 'src/static/locales/',
});

There seems to be quite an appetite for this - would love to be able to configure where my top level pages are looked for.

@malimccalla You can, check out here: https://github.com/slaterbbx/fullstackinator

Caveat

You can't change the name of the folder as far as I know, needs to stay "pages"

How

Look in the client folder, notice there are a few key things needed to make this happen. The example I show is for a custom server scenario + typescript, but its basically the same thing, the core things are.

  1. In the scripts in package.json, make sure to point to the folder ( next ./client ) instead of just ( next ) for "npm run dev" / do the same for build script
  2. In that folder ( ./client ) you will need a next.config.js file. Then simply have in it the following:
module.exports = {
    distDir: '../.next' // so that you can tell it to go up a folder for the dev and prod files.
}

If you have any questions, feel free to shoot me an email or here is fine too.

UPDATE: I just noticed that above @brainkim gives the exact same explanation.. Sorry, I will leave this though because the linked example shows a much more complex use case for anyone seeking such an example.

Thanks for this @slaterbbx

My issue is that I am trying to co-locate conceptually related code. I have the following structure

├── components
|   ├──  GridItem.tsx
|   ├──  Avatar.tsx
|   └──  Button.tsx
├── pages
|   └── profile
|       └── components
|       |   ├── CoverPhoto.tsx
|       |   └── UserInterests.tsx
|       ├── data.ts
|       ├── styles.ts
|       └── index.tsx

The issue with this approach (as pointed out by @timneutkens) is that all the files within pages are treated as webpack entry points so in turn considered for the commonchunks config. As it currently stands Next only supports top level page components within pages. If I could configure where pages are looked for I could keep this (reasonable?) structure. I imagine something like this in the config

pages: ["./pages/*/index.tsx"]

It could also be used for projects that store pages in multiple locations

pages: ["./pages/*", "./admin-pages/*"]

or projects that want to store their top level components in a folder named something differently

pages: ["./views/*"]

or projects that just want to customise the path

pages: ["./src/custom/path/to/pages/*"]

I believe this is a fair feature to have and it does not feel like a radical pattern (yarn workspaces use the same pattern to locate workspaces, a pattern Next.js itself implements).

@malimccalla ah, yea, totally understand your grief, I also desire a fully flexible solution. Possibly something worth contributing an effort too, but I have read that they are not interested in offering a solution ( somewhere, but don't quote me on that ) so I fear that investing such time into such a feature could be a lost cause. Unless of course they confirm that they would be interested in such a contribution, then again, might be a project to consider undertaking 🙋‍♂️

@malimccalla were you able to get next to play nicely with your desired project structure, or did you end up flattening out your pages directory and storing the page sub-components elsewhere?

@joncursi I managed to work around by renaming pages directory to views and then creating a new pages directory thats sole purpose is exporting the top level page components.

for example pages/profile.tsx now looks like this:

export { default } from "../views/profile"  

it's by no means ideal but allows me to keep my desired project structure

@folofse changing the i18n localePath works when it comes to scanning the directory. But when resolving language files it is removing src again. What to do?

I enabled debug to provide the logs as follows (i18next)

...
  localePath: 'src/static/locales',
  localeStructure: '{{lng}}/{{ns}}',
  localeSubpaths: 'foreign',
  backend:
   { loadPath:
      'V:/dev/some-project/static/locales/{{lng}}/{{ns}}.json',
     addPath:
      'V:/dev/some-project/static/locales/{{lng}}/{{ns}}.missing.json' },
  allLanguages: [ 'de', 'de' ],

loadPath is set to *\static\locales but it should be *\src\static\locales.

Question:

We have a custom server file in /projectRoot/next-web/server.js

It mounts /projectRoop/next-renderer-universal/client like so:

// in /projectRoot/next-web/server.js
const nextApp = next({
  dev: NODE_ENV !== 'production',
  dir: APP_DIR,
  quiet: false,
});

How the heck do we actually build and ship this :)?

@armenr This small app of mine might help. It uses a custom entry point (src/server.ts) and here is how it calls next():
https://gitlab.com/kachkaev/website-frontend/blob/e1c7106cf63811f6341c4bd47dd2354eb2546914/src/server.ts#L11-18

Keeping all source files under PROJECT_ROOT/src (or another subdirectory) is quite challenging in Next.js. Because of the added automatic TS integration in Next 9, things even become a bit more messy 😔 I wish https://github.com/zeit/next.js/issues/4315 was reopened.

:) I set up a monorepo, so the question I was asking was compounded by other complexities

We've since figured out exactly what to do, but I appreciate the sample code. Still useful! Thank you :)

@armenr What is your workaround with regards to monorepo? I set up my project with lerna and still constrained with it.

@anoop-gupt

Lerna, monorepo, yarn workspaces, and separate packages.

I put all the front-end code into a folder I call renderer-universal. I then have a package called next-web where I keep my custom next server. I also have another package where I keep nextron (next + electron...excellent project, look them up on GitHub).

In the server.js file for nextron and next-web, I use:

const nextApp = next({
  dev: NODE_ENV !== 'production',
  dir: APP_DIR,
  quiet: false,
});

And I pass in the directory location of the renderer-universal package via ENV variables to those server files.

I also have a bunch of microservices we wrote residing in other lerna packages in the monorepo as well.

No custom webpack/babel configs or symlink resolution required.

Normally, i prefer this project structure:

  - api
  - pages
  - utils

Top level src folder is normal and many projects use it. Why not ?

@revskill10 Yesh, even I preferred that structure.

We're distributing our app & services + NextJS into both desktop/cloud hybrids as well as web builds.

Package management - node_modules duplication, the need for custom serverJS files w/ Next, and shared modules and libs between the different microservices made it hard to break everything apart or follow the conventional/simpler directory structure.

To provide an easily manageable setup for my team, I had to come up with a pattern that let us work on desktop and web versions simultaneously, and to decouple all microservices and deduplicate all shared libs & modules between them. The only real "right" way to do that was via the setup I've described.

For the average project getting started, this is overkill. In our case, we had a reasonably clear understanding of our initial requirements and what we needed to build, so I was just answering the question.

For what it's worth, we're thinking of getting rid of the custom server.js file and instead moving to the /api layout that's been implemented into Next9. Unclear, as of yet, whether this will still make it easily possible for us to develop on/build web + nextron simultaneously in a simple way.

@armenr Can I have your repository location, please? It seems a good solution.

The distDir: '../dist', method no longer works in Next 9 with typescript and customer server. The problem is it creates a tsconfig.json in the src dir.

Spent a couple of hours trying to solve this but had to move everything into the root dir... such a mess 😞

image

Spent a couple of hours trying to solve this but had to move everything into the root dir... such a mess 😞

image

Nothing changes if you try messing with path resolutions, or modifying the entrypoint file in your tsconfig.json?

This has been requested since 2017. How can we help to get this feature shipped?

@timneutkens please reopen this issue and reconsider

Replied here, going to lock this issue.
https://github.com/zeit/next.js/issues/4315#issuecomment-522263598

Was this page helpful?
0 / 5 - 0 ratings