![](/img/trans.png)
[英]How do I deploy NodeJS server that's for a React Native App to Heroku?
[英]How do I deploy a static React "app" to Heroku?
标题是:如何在 Heroku 上修复“无法在模块外使用导入语句”错误而不会导致“必须使用导入来加载 ES 模块”错误?
这是在我理解我试图部署一个“静态”React“应用程序”之前,Heroku 正在运行 index.js,就好像它是服务器代码一样。
我已经设置Procfile
来包含:
web: node ./src/index.js
然后我看到了这个错误:
...
2020-03-29T02:34:01.000000+00:00 app[api]: Build succeeded
2020-03-29T02:34:02.637867+00:00 heroku[web.1]: State changed from starting to crashed
2020-03-29T02:34:02.622526+00:00 heroku[web.1]: Process exited with status 1
2020-03-29T02:34:02.583667+00:00 app[web.1]: /app/src/index.js:1
2020-03-29T02:34:02.583689+00:00 app[web.1]: import React from 'react';
2020-03-29T02:34:02.583690+00:00 app[web.1]: ^^^^^^
2020-03-29T02:34:02.583690+00:00 app[web.1]:
2020-03-29T02:34:02.583691+00:00 app[web.1]: SyntaxError: Cannot use import statement outside a module
2020-03-29T02:34:02.583691+00:00 app[web.1]: at wrapSafe (internal/modules/cjs/loader.js:1072:16)
...
我试图通过将其添加到package.json
来修复它:
"type": "module",
然后我收到了这个错误:
...
2020-03-29T03:05:01.000000+00:00 app[api]: Build succeeded
2020-03-29T03:05:06.293573+00:00 heroku[web.1]: Starting process with command `node ./src/index.js`
2020-03-29T03:05:08.744086+00:00 heroku[web.1]: State changed from starting to crashed
2020-03-29T03:05:08.724957+00:00 heroku[web.1]: Process exited with status 1
2020-03-29T03:05:08.650103+00:00 app[web.1]: internal/modules/cjs/loader.js:1174
2020-03-29T03:05:08.650125+00:00 app[web.1]: throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
2020-03-29T03:05:08.650126+00:00 app[web.1]: ^
2020-03-29T03:05:08.650126+00:00 app[web.1]:
2020-03-29T03:05:08.650126+00:00 app[web.1]: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /app/src/index.js
2020-03-29T03:05:08.650127+00:00 app[web.1]: at Object.Module._extensions..js (internal/modules/cjs/loader.js:1174:13)
2020-03-29T03:05:08.650127+00:00 app[web.1]: at Module.load (internal/modules/cjs/loader.js:1002:32)
...
我应该注意到我的 React “应用程序”只是一个前端,它使用了我已经部署在其他地方的 GraphQL API。 换句话说,没有“为 [我的] 反应应用程序提供服务的 server.js”。 ( HMR的评论让我意识到了这一点。我想正确的术语是将其称为“静态应用程序”。)
server.js
这段代码仅稍微改编自Tin Nguyen的回答作品:
const http = require('http');
const path = require('path');
const express = require('express');
let wss;
let server;
const app = express();
app.use(express.static(path.join(__dirname, './build')));
server = new http.createServer(app);
server.on('error', err => console.log('Server error:', err));
server.listen(process.env.PORT);
...使用此Procfile
:
web: node ./server.js
唯一的变化是构建目录的路径,我在使用heroku run bash
窥探后对其进行了调整。
我的网站工作不正常,但我认为这是我的构建不正确的结果。 也许这可以通过 buildpack 解决。 但这属于另一个问题。 (而且我可能不会费心去弄清楚,因为我打算听取 Tin Nguyen 的建议并尝试在 GitHub 上托管。)
更新:问题不在于我的构建,而在于客户端路由(如https://create-react-app.dev/docs/deployment/ 所述)。 此代码(来自该页面)修复了它(在server.js
):
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT);
HMR 评论中的链接帮助我达成了这种理解,但 Dave Ceddia 写道,他的文章涵盖了如何将 React 应用程序和 API 服务器保持在一起。 是否有关于如何使用已部署在其他地方的 API 服务器在 Heroku(或其他地方)上部署前端的文档?
如果我没看错,您有一个静态网站,并且希望将其托管在 Heroku 上。
静态网站可以在 Netlify 和 GitHub 页面上提供服务。 他们不需要网络服务器。 您仍然可以通过在它周围包裹一个 Web 服务器来将它托管在 Heroku 上,然后该服务器为您的静态文件提供服务。
const http = require('http');
const path = require('path');
const express = require('express');
let wss;
let server;
const app = express();
app.use(express.static(path.join(__dirname, './../build')));
server = new http.createServer(app);
server.on('error', err => console.log('Server error:', err));
server.listen(process.env.PORT);
你怎么知道你有一个静态网站?
您应该在项目中的某处生成了构建文件。 您可以导航到该文件夹并打开index.html
。 即使您没有运行node
或npm
该网站也应该可以工作。 该文件夹在我的示例./../build
。
我个人建议您通过 Heroku 在 GitHub 上托管静态网站。 Heroku 是“免费的”,但有很多限制。 dyno 时间有限,网站长时间不使用后需要启动等等。
尝试更改您的命令:
node ./src/index.js
到:
node --experimental-modules ./src/index.js
尝试使用和不使用 package.json 修复
"type": "module"
实际上,这来自在 NodeJS 环境中使用 ES6 import
。 有两种方法,在服务器端 JavaScript 文件中使用require
而不是import
:
import something from 'something';
↓↓↓
const something = require('something');
或者在服务端环境使用babel node
运行项目:
node ./src/index.js
↓↓↓
babel-node [options] [ -e script | ./src/index.js ] [arguments]
一个完整的例子可能如下所示:
npx babel-node --presets es2015 -- ./src/index.js
通过阅读您的错误,我想第二种方法更适合您的情况。 但首先请删除您的解决方案,我的意思是"type": "module",
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.