【发布时间】:2017-12-26 23:54:14
【问题描述】:
我目前正在尝试将应用程序部署到单个 Heroku dyno,它不使用 create-react-app,但有一个用于 webpack 的快速服务器和一个 rails API 后端。
我在将我的请求代理到 API 时遇到问题(但在本地工作正常),这是 Heroku 日志中的错误:
2017-12-03T16:00:18.436271+00:00 app[web.1]: Error: connect ECONNREFUSED 127.0.0.1:3005
2017-12-03T16:00:18.436308+00:00 app[web.1]: at Object.exports._errnoException (util.js:1018:11)
2017-12-03T16:00:18.436309+00:00 app[web.1]: at exports._exceptionWithHostPort (util.js:1041:20)
2017-12-03T16:00:18.436311+00:00 app[web.1]: at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
我确保将 buildpacks 用于 node 和 rails 作为described here。
以下是相关代码:
过程文件
web: npm run start:prod
api: bundle exec rails server --port=3005 --environment=production -b 127.0.0.1
package.json
{
"name": "foo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"proxy": "http://127.0.0.1:3005/",
"engines": {
"node": "6.10.2",
"yarn": "0.24.5",
"npm": "5.5.1"
},
"scripts": {
"start": "NODE_ENV=development node server",
"start:prod": "yarn run build && NODE_ENV=production node server",
"build": "NODE_ENV=production webpack -p --config ./webpack.prod.js --progress --colors --display-error-details"
},
server.js
const express = require('express');
const proxy = require('express-http-proxy');
const app = express();
const port = process.env.PORT || 3000;
const path = require('path')
const webpack = require('webpack')
const proxyHost = '127.0.0.1';
const proxyPort = '3005';
app.use('/api', proxy(`${proxyHost}:${proxyPort}`));
const isProd = process.env.NODE_ENV === 'production'
let config
if (isProd) {
config = require('./webpack.prod.js')
} else {
config = require('./webpack.dev.js')
}
const publicPath = config.output.publicPath || '/';
const outputPath = config.output.path || path.resolve(process.cwd(), 'dist');
if (!isProd) {
console.log('Development env detected: Initializing hot reloading')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const compiler = webpack(config)
app.use(webpackHotMiddleware(compiler, {
log: console.log,
path: '/__webpack_hmr'
}))
app.use(webpackDevMiddleware(compiler, {
entry: config.entry,
publicPath: config.output.publicPath,
stats: {
colors: true
}
}))
app.use('*', function (req, res, next) {
const filename = path.join(compiler.outputPath, 'index.html')
compiler.outputFileSystem.readFile(filename, (err, result) => {
if (err) {
return next(err)
}
res.set('content-type', 'text/html')
res.send(result)
res.end()
})
})
} else {
app.use(publicPath, express.static(outputPath));
app.get('*', (req, res) => res.sendFile(path.resolve(outputPath, 'index.html')));
}
app.listen(port, (err) => {
if (err) {
console.log(err.message)
} else {
console.log(`Server Started at port ${port}`);
}
});
任何帮助将不胜感激!
编辑解决方案
所以我能够根据下面接受的答案找到解决方案,但我想我会更新帖子以提供具体细节。
正如答案中所指出的,Heroku 似乎在您的 Procfile 中为每个进程使用不同的测功机,这就是前端/后端服务器最初无法相互通信的原因。
为了避免这种情况,我只是创建了一个虚拟 procfile,它使用 foreman 来初始化真正的 procfile:
Procfile(Heroku 使用的虚拟文件)
web: foreman start -f StartProcfile
StartProcfile(实际进程)
web: npm run start:prod
api: bundle exec rails server --port=3005 --environment=production
应该注意的是,在我的情况下,我遇到了超过 dyno 内存上限并且需要超过 60 秒才能绑定到分配的 heroku 端口的其他问题。原来是因为我在 web 过程中包含了构建步骤,而我应该在 package.json 中使用 postinstall 钩子。
package.json
"scripts": {
"start": "NODE_ENV=development node server",
"start:prod": "NODE_ENV=production node server --optimize_for_size --max_old_space_size=460 --gc_interval=100",
"build": "NODE_ENV=production webpack -p --config ./webpack.prod.js --progress --colors --display-error-details",
"postinstall": "npm run build"
},
【问题讨论】:
-
嗨,克里斯,我很好奇,是什么让你决定使用两个框架而不是一个?什么不是全部都在 RoR 上或全部在节点上?你介意分享吗?
-
RoR 主要是一个后端框架。它非常适合静态网站,但不适用于 React 等动态/单页面应用程序。我本可以在后端使用 node,但我对 RoR 更满意,所以我决定坚持下去。
-
谢谢。我喜欢 Ruby,但在 4.0 发布时我离开了 RoR 以选择其他选项……我注意到我只喜欢 ActiveRecord 和迁移部分,所以我取消了额外的层并在 Ruby 领域选择了更轻的选项。从未回头,但我仍然不时想知道为什么人们坚持 RoR。
标签: ruby-on-rails node.js heroku