如何构建 next.js 生产?

Posted

技术标签:

【中文标题】如何构建 next.js 生产?【英文标题】:How to build next.js production? 【发布时间】:2019-05-11 18:46:21 【问题描述】:

我尝试在 next.js 中获得一个生产版本以在我的服务器上运行它,但是当我尝试时我无法构建 next.js 生产版本

npm 运行构建

有谁知道如何让 next.js 中的 prod 构建正常工作?我在 next.js 文档中做了所有事情,但总是在下面出现此错误。如果我进行开发构建,它可以正常工作,但尝试 prod 构建会导致错误。

我也做了很多次next build并重新安装了所有仍然出现此错误的node_modules包。

它总是在终端显示我

Error: Could not find a valid build in the '/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/.next' directory! Try building your app with 'next build' before starting the server.
    at Server.readBuildId (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/next/dist/server/next-server.js:753:15)
    at new Server (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/next/dist/server/next-server.js:80:25)
    at module.exports (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/next/dist/server/next.js:6:10)
    at Object.<anonymous> (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/next.config.js:6:13)
    at Module._compile (internal/modules/cjs/loader.js:707:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:718:10)
    at Module.load (internal/modules/cjs/loader.js:605:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:544:12)
    at Function.Module._load (internal/modules/cjs/loader.js:536:3)
    at Module.require (internal/modules/cjs/loader.js:643:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at loadConfig (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/next/dist/server/config.js:47:28)
    at _callee2$ (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/next/dist/build/index.js:52:42)
    at tryCatch (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/regenerator-runtime/runtime.js:62:40)
    at Generator.invoke [as _invoke] (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/regenerator-runtime/runtime.js:288:22)
    at Generator.prototype.(anonymous function) [as next] (/mnt/c/Users/NZXT_YOLO/Desktop/New folder (2)/learnnextjs-demo/node_modules/regenerator-runtime/runtime.js:114:21)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! hello-next@1.0.0 build: `next build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the hello-next@1.0.0 build 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/kk/.npm/_logs/2018-12-10T19_58_00_588Z-debug.log

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("*", (req, res) => 
    return handle(req, res);
  );

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

next.config.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("/projects/:page", (req, res) => 
    const page = req.params.page;
    let file = "";
    switch (page) 
      case "example1":
        file = "/projects/example1";
        break;
      case "example2":
        file = "/projects/example2";
        break;
    
    return app.render(req, res, file,  page );
  );

  server.get("*", (req, res) => 
    return handle(req, res);
  );

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

package.json

 
  "name": "hello-next",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": 
    "dev": "node server.js",
    "build": "next build",
    "export": "next export"
  ,
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": 
    "@zeit/next-sass": "^1.0.1",
    "express": "^4.16.4",
    "next": "^7.0.2",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "redux": "^4.0.1",
    "video-react": "^0.13.1"
  

如果有人有想法那就太好了!我计划在我的 AWS 服务器上使用节点运行这个 next.js 站点。但要做到这一点,我需要获取 react.js 的生产版本,目前我只能运行开发版本。

希望有人有想法。

提前致谢!

【问题讨论】:

package.json中添加这一行:"start": "cross-env NODE_ENV=production node server.js"npm run build之后使用npm start 【参考方案1】:

next build 后跟 next start 应该是为生产准备构建并运行它的正确命令。

这是package.json 的示例。如果要导出应用程序以作为静态内容运行,例如将其作为静态网站托管在 s3 中,则需要运行 next export

...
"scripts": 
    "build": "next build",
    "start": "next start",
    "export": "next export"

...

确保您的package.json 中有上述脚本,然后按顺序运行以下脚本

$ npm run build 
$ npm run start

如果要使用特定端口启动应用程序,可以指定-p 端口作为npm run 命令的参数

npm run start -- -p 3232

如果你想将它合并到 CI/CD 管道中,你需要有Dockerfile,这是一个简单的例子

FROM node:alpine

#copy source 
COPY . /app

# Install deps 
RUN cd /app &&  npm install 

# Build 
RUN npm run build

ENTRYPOINT [ "npm", "run", "start" ]

仍需要更多解释或帮助,请随时发表评论,我将非常乐意提供帮助。

【讨论】:

为什么要COPY . /appcd /app?使用WORKDIR /app,然后使用. 代替/app 目录。 @Muhammad Soliman:我是 NEXT.JS 的新手,请告诉我“npm run start”的原因是什么?通常在反应中我们不执行该命令,我们直接将构建目录指向域。 @TejasPatel npm run start 应该在package.json 中运行名为start 的指定脚本——你可以随意命名脚本start。在这种情况下,它将是npm run &lt;script_name&gt; @ErikE 这只是为了以一种简单的方式阐明命令的目的,让初学者更容易理解。 @MuhammadSoliman 明白了,但我们还需要教初学者如何以“Docker 方式”编写他们的 Dockerfile,而不是用特殊的方式编写它们。了解WORKDIR 对 Dockerfiles 非常重要,以至于给初学者一个不包含它的答案更有可能阻碍他们而不是真正帮助他们,除非你在回答中给他们一个很大的提示,“不要使用这个文件原样。您应该利用 WORKDIR 正确编写 Dockerfile。”带有指向正确文档的链接或有关如何正确使用 WORKDIR 的 *** 答案。【参考方案2】:

您的server.js 配置似乎不正确。请尝试将您的所有内容从 next.config.js 移动到 server.js,确保 next.config.js 文件为空,然后创建一个新的 npm 运行脚本:

"prod_start": "NODE_ENV=production node server.js"

您的package.json 应如下所示:


  "name": "hello-next",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": 
    "dev": "node server.js",
    "build": "next build",
    "prod_start": "NODE_ENV=production node server.js",
    "export": "next export"
  ,
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": 
    "@zeit/next-sass": "^1.0.1",
    "express": "^4.16.4",
    "next": "^7.0.2",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "redux": "^4.0.1",
    "video-react": "^0.13.1"
  

确保运行:npm run build &amp;&amp; npm run prod_start

那么你应该有一个使用 next.js 运行的生产版本的 react

如果您有任何问题,请告诉我。

【讨论】:

这太简单了,现在不知道该说什么了。非常感谢!非常感谢您的帮助。 @Karim,我正在使用类似的设置(express + next.js),你能告诉我如何构建和部署 next.js 应用程序。运行下一个构建命令时,它会生成 .next 文件夹。如果我需要将我的所有应用程序源(server.js 等)移动到生产服务器并运行 npm start,我没有得到,因为我的 express.js 服务器文件没有移动/捆绑到 .next 文件夹。 @RakeshRawat 你找到解决问题的方法了吗,我也有同样的疑问:(【参考方案3】:

您必须在您的根文件夹中启动next build,而不是在.next/

【讨论】:

【参考方案4】:

我使用Passenger/nginx 作为我的next.js 应用程序的反向代理。

我使用yarn run build 构建应用程序。

这是Passenger (index.js)的入口点

/* eslint-disable */
// An optimised entry-point for Passenger/nginx Server
const path = require('path');

const nextPath = path.join(__dirname, 'node_modules', '.bin', 'next');

// strips away all arguments until it's at `node`
process.argv.length = 1;

// redefining the arguments so it's like we are running `next start`
process.argv.push(nextPath, 'start');

// start the script/bin
require(nextPath);

【讨论】:

以上是关于如何构建 next.js 生产?的主要内容,如果未能解决你的问题,请参考以下文章

Next.js 公共图像未在生产构建中显示

Next js 在生产环境中不使用 cookie

Next.js 纱线构建因 plotly.js 失败(发生构建错误 ReferenceError: self is not defined)

Firebase + Next.js 无服务器,在 GCP 上 - 如何管理登台、生产 + 本地

NextJS:如何为生产构建添加屏幕加载?

在生产中构建 Next.js 静态网站时获取错误