NextJS with Express:将文件复制到服务器并运行“npm run start”失败

Posted

技术标签:

【中文标题】NextJS with Express:将文件复制到服务器并运行“npm run start”失败【英文标题】:NextJS with Express : copying files to server and running "npm run start" fails 【发布时间】:2020-06-19 05:06:50 【问题描述】:

我正在创建一个 NextJS 应用程序,我只想将生产文件复制到我的服务器并部署该应用程序。当我不使用 Express 时,这工作得很好,但是当我使用 Express 时,应用程序不再在服务器上运行,因为它说它找不到“页面”目录。

项目结构

|- .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

我的步骤

我在本地开发应用程序并在运行“npm run dev”时对其进行测试。当应用程序准备好部署到服务器时,我将生产文件复制到服务器并部署应用程序。据我了解,构建的应用程序全部包含在“.next”目录中,因此这是我复制到服务器的唯一目录。

这是我在服务器上获取应用程序的完整步骤

    在本地开发应用程序 使用“npm run dev”在本地测试 使用“npm run build”然后“npm run start”进行本地测试 应用程序运行良好 将文件移动到服务器位置并部署
      cp .next ~/myTestFolder cp package.json ~/myTestFolder cp package-lock.json ~/myTestFolder cp next.config.js ~/myTestFolder cd ~/myTestFolder npm 安装 npm 运行构建 npm 运行开始 应用程序运行良好

当我使用 Express 时进程失败

一旦我使用 Express,这个过程就不再有效。我需要使用 express 和 dotenv,这样我就可以为我的应用程序拥有一个可自定义的 basePath,它在我将应用程序部署到的不同服务器上可能会有所不同(请参阅我的其他堆栈溢出问题:NextJS deploy to a specific URL path)

我做了以下事情:

安装新的依赖项

npm install --save express dotenv

创建一个“.env”文件

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

更新“next.config.js”以从“.env”读取变量并传递给 WebPack,以便在“.js”文件中使用它

// 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))    
        ....
    
    ....
 

更新“package.json”中的脚本

"scripts": 
    "dev": "node s-s-r-server.js",
    "build": "next build",
    "start": "node s-s-r-server.js"
,

创建一个“s-s-r-server.js”文件来做路由

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`)
  )
)

更新任何“链接”以使用此路径

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

我可以使用“npm run dev”和“npm run build”/“npm run start”在本地运行应用程序。

但是,当我将文件复制到我的服务器位置时,它现在失败了。我复制了所有与上面相同的文件,并添加了 2 个新文件

cp s-s-r-server.js ~/myTestFolder cp .env ~/myTestFolder

我运行“npm build”OK,但是当我运行“npm run start”时它失败了

$ npm run start

> React_s-s-r@1.0.0 start /home/myTestFolder
> node s-s-r-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/s-s-r-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_s-s-r@1.0.0 start: `node s-s-r-server.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the React_s-s-r@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

知道我错过了什么/做错了什么吗?

【问题讨论】:

你还需要复制.next文件夹,因为这是next的输出 我需要查看您项目中的文件夹结构。错误消息很清楚couldn't find pages folder in your root folder,意味着您将pages 文件夹放在specified name 文件夹中的某个位置。 felixmosh - 我确实复制了“.next”文件夹,请参阅我的步骤 5.1 Darryl RN - 我已更新原始问题以包含我的项目结构 我在下面看到你的评论,你能不能先复制 pages 文件夹看看它是怎么运行的? 【参考方案1】:

错误清楚地表明:

Error: &gt; Couldn't find apagesdirectory..

你也必须cp pages ~/myTestFolder

【讨论】:

当然,通过将“页面”复制到我的测试文件夹,我复制的是开发代码,而不是构建的应用程序。据我了解,构建的应用程序是“.next”下的所有内容,因此这就是我需要部署到我的实际服务器的全部内容。 加上复制“.next”是我不使用 Express 时所需要的。一旦使用 Express,它就会失败。【参考方案2】:

这里是解决方案。 这样,您就不需要伪造副本来使服务器正常工作。 创建并将 args 传递给下一个构造函数:

// Add path module
const path = require('path')

// Init the Next app with args: 
const app = next( dir: path.join(__dirname, '..', 'yourwww'), dev )

【讨论】:

以上是关于NextJS with Express:将文件复制到服务器并运行“npm run start”失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 NextJS API 发送文件作为响应

使用 NextJS + Express 在本地主机上进行 HTTPS

NextJS vs Express [关闭]

NextJS,Express,WebSocket 握手期间出错:意外响应代码:200

Router.push 没有重定向我; Nextjs 与 Express 服务器

NextJS 应用程序和 express 服务器之间的内部 API 调用和通信