vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.91k stars 26.87k forks source link

Firebase example: couldn't find a `pages` directory #8893

Closed matchatype closed 3 years ago

matchatype commented 5 years ago

Bug report

My project has a custom structure but so far it worked pretty well. Since I updated to v9.0.7 I get this error:

Error: > Couldn't find apagesdirectory. Please create one under the project root at Object.findPagesDir [...]

So far running next src/app worked just fine. Is there anything different I should do now?

Screenshot

image

System information

ijjk commented 5 years ago

Hi, I'm not able to reproduce this with a minimal repro of the above structure. Can you provide more detailed steps to reproduce? Is the current working directory you're running Next.js from the project root?

Screen Shot 2019-09-28 at 17 51 55
matchatype commented 5 years ago

@ijjk the project structure is very similar to the with-firebase-hosting example. Yes, I'm running npm run serve from the project root.

matchatype commented 5 years ago

Quick note: I can run next as next src/app too, or npm run dev according to my scripts in the screenshot on default port 3000, it is the built project that will crash: npm run serve, which runs fine till v9.0.6.

[edit] Sorry, it will take you to setup a firebase project, but the example repo will reproduce the issue.

wouterds commented 5 years ago

Can confirm it's an issue in 9.0.7 when using src/pages for production builds.

yestoall commented 5 years ago

same problem for me trying to deploy to firebase with nextjs 9.0.2 seems to work

merrywhether commented 5 years ago

I'm seeing this too, arising from a docker config that starts the app from a few directories above the app directory (for which I've previously set the dir option on the next() constructor), while also having deleted the source pages directory before building my final docker stage.

As a workaround, it appears that I can literally mkdir pages in my app directory and everything works without having to make any other changes. Seems like it's a really shallow check and then things proceed with the actual built files as before.

wouterds commented 5 years ago

Working again in v9.0.8-canary.0, thanks for fixing so quickly guys!

cinnabarhorse commented 5 years ago

I am using 9.0.6 and can confirm this error as well. It was working before and then suddenly just broke itself. Cost me 2 days of debugging. Thank god someone finally reported this on Github... Tried updating to 9.0.8-canary.0 and still got the error. Rolling back to 9.0.4 for now.

wouterds commented 5 years ago

I am using 9.0.6 and can confirm this error as well. It was working before and then suddenly just broke itself. Cost me 2 days of debugging. Thank god someone finally reported this on Github... Tried updating to 9.0.8-canary.0 and still got the error. Rolling back to 9.0.4 for now.

How do you start your next app? Do you use a src folder?

Before 9.0.7 if you wanted to use a src folder you had to use a workaround and start your Next application like this next src. Since 9.0.7 they added official support and you can get rid of the last argument and start your app like this next.

cinnabarhorse commented 5 years ago

I'm using NextJS with firebase functions, so when I deploy I use next build src/client

notthatnathan commented 5 years ago

Same here, with latest canary (9.0.8-canary.4). I'm closely following the with-firebase-hosting example. I was able to deploy before I updated from v7 to 9.

FWIW, I'm able to skip the 'pages' directory error by adding cross-env NODE_ENV=production to the beginning of the deploy script: https://github.com/zeit/next.js/blob/canary/examples/with-firebase-hosting/package.json#L13.

But then I run into a "Could not find a valid build in the '[project root]/.next' directory!" error, which is weird since my distDir is [project root]/dist/functions/next.

And finally, npm run serve works if I change the dist dir to dist/functions/.next instead of dist/functions/next, otherwise I get a similar error: "Could not find a valid build in the '[project root]/dist/functions/.next' directory!" It seems across the board my dist dir name is being ignored in favor of the default .next.

qlerebours commented 5 years ago

@notthatnathan I tried what seems to work for you but it's not working for me. Using cross-env NODE_ENV=production removed the error about pages not found, but I still have the error concerning the invalid production build. The error is Error: Could not find a valid build in the '/home/myhome/projectRootDirectory/next' directory! Try building your app with 'next build' before starting the server. When the next folder is in /home/myhome/projectRootDirectory/src/functions/next The next project and config is in /home/myhome/projectRootDirectory/src/app/next.config.js I tried many things like:

Nothing works :-/

yestoall commented 5 years ago

not working for me again with 9.0.8, same page folder errors and /_app page size is huge at the same time

note: everything works with 9.0.2

notthatnathan commented 5 years ago

@qlerebours That's actually exactly what's happening for me, unfortunately.

Timer commented 5 years ago

This error occurs because the Firebase server is trying to boot Next.js in development mode.

As such, this error is expected -- Next.js is telling you that there's no pages/ directory to start the dev server with.

You need to boot the Next.js production server using strictly production mode.

I'm closing this because Next.js is correctly erroring, as it should. I could only reproduce this locally when trying to incorrectly boot the production server.

Likely, the src/functions/index.js file should be edited, replacing:

var dev = process.env.NODE_ENV !== 'production'
var app = next({
  dev,
  conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})

With:

var app = next({
  dev: false,
  conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})

(it's never valid to run a production build in dev mode, this error is preventing you from a bad experience)

Timer commented 5 years ago

cc @jthegedus could you please fix the example to never allow a production build to boot in dev mode?

notthatnathan commented 5 years ago

@Timer I'd actually had that thought based on experimenting with NODE_ENV, but it's not fixing it for me. With dev: false in functions/index.js, deploy says it can't find a valid build in [project root]/.next and serve says it can't find a valid build in [project root]/dist/functions/.next.

The build seems fine and is in [project root]/dist/functions/next.

Timer commented 5 years ago

@notthatnathan please provide a fully reproducing example so we can try to identify what's wrong with the setup.

notthatnathan commented 5 years ago

Well, I thought I'd reproduced it with the with-firebase-hosting example, but it actually works there with dev: false, so clearly I have something else not quite right. Sorry, nothing to see here.

yestoall commented 5 years ago

still not working with 9.1.0 seems like it trying to find next folder in different place...

in my case in my firebase.json i have... { "hosting": { "public": "dist/public", ... { "source": "**", "function": "app-next" } ], "predeploy": "yarn build-public" }, "functions": { "source": "dist/functions", ... } }

so it must try to find next folder inside dist/functions but its not working

any ideas?

yestoall commented 5 years ago

@Timer any news with that issue?

jthegedus commented 5 years ago

A bad answer I know, but I won't have time to look at this (and submit a correction) for another day or two. My most up to date usage of Next.js with Firebase is here.

Off the top of my head, I don't recall firebase serve supporting hot-reloading, so the "local testing" I was suggesting doing with the firebase serve command was of a production build before pushing it to Firebase Hosting.

Using firebase serve is to check that Firebase url rewriting works as opposed to using it to do the development of the app.

Apologies for not getting back sooner.

jthegedus commented 5 years ago

My investigations have revealed this:

Updating next to v9.1.1 works without issue.

Also, logging the dev status

var dev = process.env.NODE_ENV !== 'production'
console.log(dev)
var app = next({
  dev,
  conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})

results with false when running npm run serve which is as I expect because cross-env NODE_ENV=production firebase serve should run a production build.

@timneutkens can you shed more light on removing this flag? I'm seeing the NODE_ENV=production firebase serve command of a next build (the preserve script) run the app and server in production mode. This is what I expect to happen.


Clarification of firebase serve command. It is intended to test before deploying, not as a realtime development tool.

🚨 🚨 🚨 🚨 🚨

🚨 🚨 🚨 🚨 🚨

Firebase have been working on an improved local development experience:

try firebase emulators:start --help in your CLI

It supports:


So just to clarify, everyone is seeing this issue when running firebase serve via the serve pkg.json script?

My recommendation is to not use firebase serve, update firebase-tools and try out firebase emulators:start instead as I believe it will do as people initially expect.

yestoall commented 5 years ago

for me is not working with 9.1.1, only with 9.0.6 or before

compiling with working version (9.06) my _app.js size is 31kb but with not working (9.1.1) _app.js size is 387kb

maybe it helps to reserach the bug

timneutkens commented 5 years ago

@yestoall

compiling with working version (9.06) my _app.js size is 31kb but with not working (9.1.1) _app.js size is 387kb

https://github.com/zeit/next.js/issues/8916

yestoall commented 4 years ago

still doesn't work in 9.1.2 only with 9.0.6 i could deploy my app

any news?

ikki-nakamura commented 4 years ago

I changed the package.json

from

"deploy": "firebase deploy",

to

"deploy": "NODE_ENV=production firebase deploy",

and it worked!

timneutkens commented 4 years ago

@yestoall

still doesn't work in 9.1.2
only with 9.0.6 i could deploy my app

any news?

The issue is open, has labels "good first issue" and "help wanted" so you're free to open a PR to solve the issue or try and investigate.

paintedbicycle commented 4 years ago

I too have not been able to deploy since 9.0.6. I've tested each release as they came out, but nothing worked. I put some time into it recently and below is my solution.

The distDir path in both the docs and the above snippets didn't work for me. I'm wondering if this helps anyone else or perhaps it was something unique about the way I have my project set up?

Looking at the error logs while using the version from the examples and the above snippets, next was looking in dist/functions/app/next while the file was actually in dist/functions/next

The docs say distDir: '${path.relative(process.cwd(), __dirname)}/next' while most of the examples in the wild say distDir: 'next'. The former leads to the path problem listed above and the latter looks for the build file in a next folder inside the project root. The build file is in neither place.

If you hardcode the distDir to /dist/functions/next trying to fix the path issue shown above, that will work locally and it'll start to deploy and get much farther than before but then all your cloud functions will explode so you need to use the relative version using the path module (see code below).

I was using the distDir: 'next' for a very long time because it was in the original @jthegedus blog posts I believe (and so I think a lot of people with older projects likely have the same), but then everything broke after 9.0.6

In app.ts

import * as path from 'path'

...

const app = next({
  dev: false,
  conf: { distDir: `${path.relative(process.cwd(), __dirname)}/../next` }
});

(Note the /../ in the distDir path)

Things deploy fine for me now.

If that works for others, we really need to get all the docs and all the old blog posts updated. It was really hard tracking this down since there were lots of path changes lately and I was seeing pages directory errors, public directory errors, Could not find a valid build errors, and then the suggestions in a few issues of dev: false instead of the var dev = process.env.NODE_ENV !== 'production' version or node_env=production in your package.json being the culprit (neither of which seem to be). I found it to be a game of wac-a-mole where once I fixed one error, I'd get the other.

LMK if that solves this issue for you and I'll submit a PR with some updates to the firebase examples. Don't want to make any changes if this was only a quirk of my install.

My setup (should be pretty normal - based on the Firebase examples)

src/
--app/
--functions/
--public/
--stylesheets

dist/
--functions/
----app/
----next/
--public/
SuigetsuSake1 commented 4 years ago

Thanks @paintedbicycle after setting dev: false i had the same issue with the distDir that was not found and after using your fix it is working, however i had the next directory inside "functions" , i am using the with-firebase-hosting-and-typescript sample though so it may not be up to date.

{ distDir: `${path.relative(process.cwd(), __dirname)}/../functions/next` }
paintedbicycle commented 4 years ago

Glad it worked. Strange though that you had to change your path as my next/ folder is also inside functions. Either way, glad we're narrowing in on the issue

movewedoo commented 4 years ago

Thanks @paintedbicycle . After your update and @SuigetsuSake1 tweak it works to me great!

jthegedus commented 4 years ago

@paintedbicycle Thanks for your detailed report.

It is odd that some people are having to change the location of their next/ folder though 🤔

scottie-schneider commented 4 years ago

I'm very frustrated after trying nearly all of these solutions and no luck lol. Where is everyone finding an up to date example of how to get this to work?

Ferezoz commented 4 years ago

@scottie-schneider I got it working with what @SuigetsuSake1 commented:

// src/functions/index.ts
next({ dev: false, conf: { distDir: `${path.relative(process.cwd(), __dirname)}/../functions/next` } })

What's exactly your issue?

xaphod commented 4 years ago

I'm also stuck when trying to run firebase emulator with firebase emulators:start --inspect-functions --only functions,hosting. I'm on next version 9.3.0.

// app/index.js: 

const next = require('next');
const path = require('path');

const dev = process.env.NODE_ENV !== 'production';
console.log(`app/index: dev=${dev}`);
const app = next({ dev, conf: {distDir: `${path.relative(process.cwd(), __dirname)}/../functions/next` }});

module.exports = {
  app,
};
// functions/index.js:
const functions = require('firebase-functions');
const { app } = require('../app');

const handle = app.getRequestHandler();

exports.next = functions.https.onRequest(async (req, res) => {
  console.log('File: ' + req.originalUrl); // log the page.js file that is being requested
  await app.prepare();
  handle(req, res);
});

Error:

>  app/index: dev=true
⚠  Error: > Couldn't find a `pages` directory. Please create one under the project root
    at findPagesDir (/Users/tim/iPhone-dev/project/app/node_modules/next/dist/lib/find-pages-dir.js:3:170)

I made sure that next build has run, and I see its output under functions/next: folders like cache, server, static... I don't know where the "project root" is (I suppose functions/next), and I don't see a pages directory anywhere after build.

Update: did some console.log in find-pages-dir.js findPagesDir(), looks like it's looking for pages under functions/ which makes no sense. Is it looking for built stuff or the actual pages source in app/pages ? I suppose the latter, which is the issue.

Ferezoz commented 4 years ago

@xaphod Maybe you are missing to set your node environment to production like this:

NODE_ENV=production firebase emulators:start --inspect-functions --only functions,hosting

or by directly setting it in next configuration in app/index.js like this:

next({ dev: false })
huan231 commented 4 years ago
const app = next({
    dev,
    dir: path.join( __dirname, '../app'),
});

works fine for me

ryudice commented 4 years ago

Is this getting fixed someday? I'm having the same issue, seems it's been a while.

scottie-schneider commented 4 years ago

@ryudice what worked for me:

  1. Downloaded the latest example of the with-firebase-hosting
  2. Changed the node engine to 10 "engines": { "node": "10" },
  3. Installed next@latest "next": "^9.3.4",
scottie-schneider commented 4 years ago

Additionally, it seems that cloud functions meant to be publicly accessed (like the all important functions/index.js) need to be specifically assigned permissions moving forward.

Once I had this working, without setting the access level for allUsers, I got an 'your app is not authorized to view this resource' error when going to my hosting URL. Hope that helps someone coming next (or me, when I forget I solved this and come back to this thread in 2 months).

Screen Shot 2020-04-01 at 6 13 00 PM

Reference: https://forum.serverless.com/t/setting-iam-policies-for-google-http-functions-since-all-new-gcloud-http-functions-after-nov-1-2019-will-default-private/8686

honi commented 4 years ago

Do you people actually have acceptable performance using a Firebase Function (in reallity just a Google Cloud Function behind the scenes)?

I ended up switching to a e2-micro instance on Google Cloud (just a vm) with the next.js app running 24/7. For my use case this is acceptable money wise, and I don't need the theoretical infinite scalability of a cloud function to be honest.

After all the config fighting and testing, I just feel it's not there yet. In theory it seemed like a good idea and a nice one as well (firebase deploy and there you go). This is my own experience with my current projects, so take this with a grain of salt. 🤷‍♂

rosgoo commented 4 years ago

@scottie-schneider I'm having the same issue but using node 10 and latest next version did not fix it for me :( are you using the latest typescript or regular example? Also are you just testing by running npm run serve or are you using preserve first ? Thank you!

scottie-schneider commented 4 years ago

@ryan-0 sorry for late response here. Have you tried adjusting the cloud functions permissions level (my next post after the one you tried)?

rosgoo commented 4 years ago

Thanks for your replay @scottie-schneider! I figured it out in the end, it was an issue with the distDirin my webpack config... Now onto figuring out why hooks only sometimes work when I try npm run serve. Thanks for your help!

vzla0094 commented 4 years ago

Additionally, it seems that cloud functions meant to be publicly accessed (like the all important functions/index.js) need to be specifically assigned permissions moving forward.

Once I had this working, without setting the access level for allUsers, I got an 'your app is not authorized to view this resource' error when going to my hosting URL. Hope that helps someone coming next (or me, when I forget I solved this and come back to this thread in 2 months).

Screen Shot 2020-04-01 at 6 13 00 PM

Reference: https://forum.serverless.com/t/setting-iam-policies-for-google-http-functions-since-all-new-gcloud-http-functions-after-nov-1-2019-will-default-private/8686

@scottie-schneider Thank you very much for sharing this! you're a life saver. I couldn't figure out why I was getting the error Your client does not have permission to get URL /next/ from this server. and after googling for a long time I stumbled upon your solution, it saved me a lot of time reading documentation

mattgabor commented 4 years ago

This is still happening for me, and the only way I've been able to fix it is by setting NODE_ENV=production which is not ideal since I would like to reserve NODE_ENV for things like environment scripts. Is the directory named functions enforced by firebase? This is my current setup

const dev = process.env.NODE_ENV !== 'production';
const app = next({
  dev,
  // the absolute directory from the package.json file that initialises this module
  // i.e.: the absolute path from the root of the Cloud Function
  conf: { distDir: 'dist/client' },
});
Ferezoz commented 4 years ago

@mattgabor then just set the flag directly as:

next({ dev: false })

And delete:

const dev = process.env.NODE_ENV !== 'production';

That way you could still use NODE_ENV.

mattgabor commented 4 years ago

I see, thanks @ferezoz. I thought always disabling dev mode would prevent hot reloading or source maps when running next dev but it seems not to. What does dev mode actually do then? The docs just say dev (bool) whether to launch Next.js in dev mode - default false

SaschaHeyer commented 4 years ago

What is the recommended solution for this issue?