Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

reactjs - NextJS with Express : copying files to server and running "npm run start" fails

I am creating a NextJS application and I want to copy ONLY the production files to my server and deploy the application. This works perfectly fine when I do NOT use Express, however when i do use Express the app no longer runs on the server as it says it can not find the "pages" directory.

Project structure

|- .next
|- client
     |- polyfills.js
|- components
     |- CompA.js
     |- CompB.js 
     |- etc
|- node-modules
     |- ...
|- pages
     |- index.js
     |- page1.js
     |- page2.js
     |- etc
|- public
     |- appIcon.png
|- scripts
     |- utils.js
|- stylesheets
     |- main.css
|- next.config.js
|- package-lock.json
|- package.json

My steps

I develop the application locally and test it my running "npm run dev". When the app is ready to deploy to a server I copy JUST the production files to the server and deploy the application. It is my understanding that the built application is ALL contained in the ".next" directory, therefore this is the only directory I copy to my server.

Here are my full steps in order to get the application on the server

  1. Develop the application locally
  2. Test locally using "npm run dev"
  3. Test locally using "npm run build" and then "npm run start"
  4. Application runs perfectly fine
  5. Move the files to the server location and deploy
    1. cp .next ~/myTestFolder
    2. cp package.json ~/myTestFolder
    3. cp package-lock.json ~/myTestFolder
    4. cp next.config.js ~/myTestFolder
    5. cd ~/myTestFolder
    6. npm install
    7. npm run build
    8. npm run start
    9. Application runs perfectly fine

The process fails when i use Express

As soon as I use Express, this process no longer works. I need to use express and dotenv so I can have a customizable basePath for my application which can differ on the different servers I deploy my application to (see my other stack overflow question : NextJS deploy to a specific URL path)

I did the following:

Install the new dependencies

npm install --save express dotenv

Create a ".env" file

BASE_PATH=/my-test-application/path-for-my-app

Update "next.config.js" to read the variables from ".env" and pass to WebPack so it can be used in ".js" files

// support getting variables from the server environment
const { parsed: localEnv } = require('dotenv').config()
const webpack = require('webpack')

module.exports = {
    // Stop being being able to access pages without using proper URL
    useFileSystemPublicRoutes: false,

    webpack: function(cfg) {
        // pass the environment variables to webpack so JS files can access them
        cfg.plugins.push(new webpack.EnvironmentPlugin(localEnv))    
        ....
    }
    ....
 }

Update the scripts in "package.json"

"scripts": {
    "dev": "node ssr-server.js",
    "build": "next build",
    "start": "node ssr-server.js"
},

Create a "ssr-server.js" file to do the routing

const express = require('express')
const next = require('next')

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  server.get('/my-test-application/path-for-my-app', (req, res) => {
    return app.render(req, res, '/index', req.query)
  })

  server.get('/my-test-application/path-for-my-app/page1', (req, res) => {
    return app.render(req, res, '/page1', req.query)
  })

  server.get('/posts/:id', (req, res) => {
    return app.render(req, res, '/posts', { id: req.params.id })
  })

  server.all('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
  })
})

Update any "Link"s to use this path

render(){
    let basePath = process.env.BASE_PATH? process.env.BASE_PATH: "";
    ...
    <Link href={`${basePath}/page1`}> 
    ...

I can run the application locally using "npm run dev" and "npm run build"/"npm run start".

However when I copy files to my server location it now fails. I copy all the same files as above with the addition of the 2 new files

  • cp ssr-server.js ~/myTestFolder
  • cp .env ~/myTestFolder

I run "npm build" OK, but when I run "npm run start" it fails with the following

$ npm run start

> React_SSR@1.0.0 start /home/myTestFolder
> node ssr-server.js

/home/myTestFolder/node_modules/next/dist/lib/find-pages-dir.js:3
if(existsSync(_path.default.join(dir,'..','pages'))){throw new Error('> No `pages` directory found. Did you mean to run `next` in the parent (`../`) directory?');}throw new Error("> Couldn't find a `pages` directory. Please create one under the project root");}
                                                                                                                                                                   ^
Error: > Couldn't find a `pages` directory. Please create one under the project root
    at findPagesDir (/home/myTestFolder/node_modules/next/dist/lib/find-pages-dir.js:3:170)
    at new DevServer (/home/myTestFolder/node_modules/next/dist/server/next-dev-server.js:1:3830)
    at createServer (/home/myTestFolder/node_modules/next/dist/server/next.js:2:105)
    at Object.<anonymous> (/home/myTestFolder/ssr-server.js:5:13)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! React_SSR@1.0.0 start: `node ssr-server.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the React_SSR@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/myTestFolder/.npm/_logs/2020-03-06T10_24_04_105Z-debug.log

Any idea what I am missing/doing wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The error clearly says:

Error: > Couldn't find apagesdirectory..

you have to cp pages ~/myTestFolder as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...