ある日、Nuxt.jsでgenerateしたら「connect ECONNREFUSED 127.0.0.1:3000」というエラーが頻発していくつかのページが表示されなくなりました。
原因と解決策を調べていきます。
WordPressの上でな!
※ このブログはまだWordPress製です
このページの目次
エラー「connect ECONNREFUSED 127.0.0.1:3000」が起きた
えー、何やらかんやら更新していつも通りデプロイしました。
するとズラズラっと並ぶ以下のエラー。
Error: connect ECONNREFUSED 127.0.0.1:3000
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)
ローカル環境でビルドのテストせずにいきなりデプロイしてしまったので、サイトを数時間機能停止させてしまいました…。
エラーが起きていたページ
エラーが起きていたのは全てAPIと通信していたページでした。
「127.0.0.1:3000」に立てていたAPIサーバと通信ができないエラーのようです。
該当ページをブラウザで開くと「500 Network Error」で表示されず、それ以外のページは表示できていました。
「connect ECONNREFUSED 127.0.0.1:3000」の原因と解決策
エラー名でそのまま検索すると原因および解決策が分かりました。 見つけた場所(英語)です。
要約すると、「SSR時にNuxt.jsで立てていたAPIサーバはgenerate時には落ちているからだよ。JSONから手動で読み込みなさいよ」みたいな?
こんな↓風にAPIから取得していたデータを…。
export default {
async asyncData ({ app }) {
const posts = await app.$axios.get('/api/posts')
return {
posts: posts.data,
}
},
}
こんな↓風に静的なJSONファイルから読み込みなさいってことみたいです。
import json from '~/static/api/posts.json'
export default {
data() {
return {
posts: json,
}
},
}
この問題は外部にAPIサーバがある時は起きなさそう
この問題は、Nuxt.jsでSSR時に立てていたAPIサーバが、generateの際には起動していないせいで起こります。
なので、WordPressのREST APIとかその他のヘッドレスCMSのAPIからデータを取得している場合には起きないでしょう。
この解決策の問題点
静的なJSONファイルをあらかじめ用意しておかなければならない点だと思います。
APIって要はデータベースと通信するわけだから、もっと動的な使い方をすることが多いと思うんですよね。 フィルタかけたりとか。 その場合は、JSONを出力する手間、データ取得後のフィルタ処理、最新の内容とのズレなど、考えないといけないことが出てきそうです。
記事公開>ビルド、だから別にいいのか。 使い方によるのかな。
僕の場合は、素人故にたまたまこの解決法に適性の高い構造になっていて、
- APIが通信するデータベースもローカルにある
- 開発時にはデータベースから直接データを取得
- その際に静的JSONを出力
- ビルド時には静的JSONからデータを取得(axios経由)
のような不格好な処理になっていました。
ビルド時にJSONからデータ取得するのをaxios経由させずにimportに変更するだけで元の通りに動きました。
import posts_json from '~/static/api/posts.json'
export default {
async asyncData ({ app, isDev }) {
let posts = posts_json
if ( isDev ) {
posts = await app.$axios.$get('/api/posts')
}
return {
posts: posts,
}
},
}
初期値として静的JSONからのデータを代入しておき、開発中ならaxiosでAPIと通信して上書きします。
axios経由の方が「posts.data」の形じゃなくなっていますが、「get」に$マークをつけると戻り値が「.data」の中身になります。 何故そうなるのかはまだ調べていません。
他の解決策はないのか
「or using a mounted hook」と書いてありました。
但し書きに「but then the info isn't included in the HTML」とあるので、おそらく「asyncDataじゃなくてmountedを使いなさい」ってことだと思います。 mountedでAPIと通信した場合は、出力したHTMLにその内容が出力されないので。
というわけで、先ほどのasyncDataでの処理をmountedへ移植↓。
export default {
data() {
return {
posts: posts,
}
},
mounted() {
axios.get('/api/posts').then(res => {
this.posts = res.data
})
},
}
確かにエラーが出なくなりました。
う~ん、JSON出力のデメリットをとるのか、HTMLに出力されないデメリットをとるのか。 悩ましいところですねこれ。
原因と対策は分かったが、何故起こったのかが分からない
今回、generate時にはAPIと通信できないエラーにぶち当たりました。
原因はgenerateの際にはAPIサーバが立っていないことで、解決策は静的JSONを用意してやることでした。
原因・対策ともに、非常によく理解できる内容です。
でもね?
前回のビルドまではgenerateの時でもaxios経由でAPIと通信してたんですよ。
何故急にこんなことになったのか。
コレガワカラナイ。
前回のビルド以降やったこと
PWAというモジュールを導入しました。
その際にnpmに何やらかんやら言われたので、npm自体をアップデート。
npmのアップデートあるってことは、Nuxtやその他モジュールもアップデートあるんじゃね?
とNuxt.jsを2.13.0から2.14.3へアップデート。
その他アップデートしたモジュール↓。
- @nuxtjs/axios:5.12.0→5.12.1
- @nuxtjs/google-analytics:2.3.0→2.4.0
記憶にある変更はこのくらい。
おそらく上記内容は原因ではない
というのも、先ほどのスレッド。 2018年の投稿なんです。
Nuxt.jsやモジュールのアップデートで起きたとは考えにくいです。
新規に導入したPWAモジュールについても、オフにしても同じ症状だったので関係ないと思います。
なら何故急に起きたのか。
誰か教えてください。
改善できたとは言え、以前の環境の方がだいぶ開発しやすかったです…。
まとめ
Nuxt.jsでgenerate時にエラー「connect ECONNREFUSED 127.0.0.1:3000」が出た場合、generateの際にはAPIサーバが立っていないことが原因でした。
解決にはAPIの内容を静的JSONで出力しておいて直接import、またはasyncDataではなくmountedでAPIと通信する必要があるそうです。
でもね、ちょっと前まではこんなこと考えなくてもgenerateでAPIと通信してたんですよ。
何か…何かアルハズ…。
以上、WordPressからお届けしました!