Next は、React フレームワークであり、フロントエンドとバックエンドを一体化させることができ、プロジェクトには良い選択肢です。この記事では、数日前にクロスオリジンの問題を解決するための開発プロセスを記録します。【推奨案 2、案 2 はより簡単ですが、少しの Node.js の基礎知識が必要です】
開始する前に、クロスオリジンの API が正常に呼び出せることを確認してください。実践中にエラーが発生した場合は、まず API が正常であるかを確認し、次にローカルのクロスオリジンの設定に問題がないかを確認してください。半日忙しかった後に元々の API に問題があることに気付くのを避けてください :@(装大款)
案 1:プロジェクトディレクトリに server.js
ファイルを作成し、package.json のスクリプトオプションを使用して、開発環境でクロスオリジンを実現します。#
実装 >>>#
server.js
ファイルを作成し、ディレクトリはプロジェクトのルートディレクトリ、つまりpackage.json
と同じ階層になるようにします。ファイルのコードは以下の通りです。
// server.js
const express = require('express')
const next = require('next')
const { createProxyMiddleware } = require('http-proxy-middleware')
//クロスオリジンの具体的な設定はここに記述します
const devProxy = {
'/email': {
target: 'https://api.postmarkapp.com/',
changeOrigin: true
}
}
//以下の内容は変更しないでください。わからない場合は変更しないでください
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()
if (dev && devProxy) {
Object.keys(devProxy).forEach(function (context) {
// http-proxy-middlewareの新しい使用法2
server.use(createProxyMiddleware(context, devProxy[context]))
})
}
server.all('*', (req, res) => {
handle(req, res)
})
server.listen(port, err => {
if (err) {
throw err
}
console.log(`> Ready on http://localhost:${port}`)
})
})
.catch(err => {
console.log('An error occurred, unable to start the server')
console.log(err)
})
- 例では、postmark のメール送信 API を呼び出しています。元の API のアドレスは
https://api.postmarkapp.com/email
で、get
リクエストです。 - 上記の方法で実際のリクエストは以下のようになります。
import axios from "axios";
export const waitlistEmailSend = (data: any) => {
return new Promise((resolve, reject) => {
try {
axios({
method: "post",
url: "/email",
data,
headers: {
Accept: "application/json",
"X-Postmark-Server-Token": "***TOKEN***",
"Content-Type": "application/json",
},
}).then((res: any) => {
// console.log(res.code);
if (res.status == 200) {
resolve(res);
} else {
reject(res);
}
});
} catch (error) {
console.error(error);
reject(error);
}
});
};
- package.json でクロスオリジンを設定し、
"dev:node-middleware": "node server.js"
を使用してプロジェクトを起動し、上記で作成したリクエストを呼び出します。npm run dev:node-middleware
を使用してプロジェクトを起動します。
{
...
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"dev:node-middleware": "node server.js"
}
...
}
- ローカルの
/email
インターフェースにリクエストを送信し、実際のリクエストはミドルウェアによってhttps://api.postmarkapp.com/email
に転送されます。クロスオリジンが成功し、F12 のネットワークリクエストでは localhost に対するリクエストと表示されます。
案 2:クロスオリジンインターフェースを Next の組み込みバックエンド API にカプセル化し、フロントエンドのリクエストでクロスオリジンを実現します。#
通常、Next で作成したプロジェクトには
pages/api/hello.ts
というファイルがあります。api フォルダは Next の組み込みの Node.js バックエンドであり、ここでクロスオリジンインターフェースを呼び出すと、クロスオリジンエラーは発生しません。実際には非常に理解しやすいです。バックエンドはローカルのようなものであり、すべてのリクエストは直接発行されるため、フロントエンドのように独自のドメインを持っていません。したがって、クロスオリジンの問題は存在しません。
もし Node.js を理解している場合は、チュートリアルをスキップしても構いません。すべては Node.js のバックエンドの使用法と同じです
実装 >>>#
pages/api/waitlistemail.ts
に Next のバックエンド API を作成します。サンプルコードは以下の通りです。
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import axios from "axios";
import type { NextApiRequest, NextApiResponse } from "next";
type Data = {
code: number;
data: any;
errMsg: string;
};
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
console.log(req.body);
if (req.body.To) {
console.log("send");
try {
axios({
method: "post",
url: "https://api.postmarkapp.com/email",
data: req.body,
headers: {
Accept: "application/json",
"X-Postmark-Server-Token": "***TOKEN***",
"Content-Type": "application/json",
},
}).then((r: any) => {
console.log(r.status);
if (r.status == 200) {
res
.status(200)
.json({ code: 0, data: "", errMsg: "Email send success!" });
} else {
res
.status(200)
.json({ code: 1, data: "", errMsg: "Email send fail!" });
}
});
} catch (error) {
res
.status(200)
.json({ code: 1, data: "", errMsg: "Email send success!" });
}
} else {
res.status(200).json({ code: 1, data: "", errMsg: "Email send fail!" });
}
}
- Next のフロントエンドで API を呼び出すコードは以下の通りです。
import axios from "axios";
export const waitlistEmailSend = (data: any) => {
return new Promise((resolve, reject) => {
try {
axios({
method: "post",
url: "/api/waitlistemail",
data,
}).then((res: any) => {
// console.log(res);
if (res.data.code == 0) {
resolve(res);
} else {
reject(res);
}
});
} catch (error) {
reject(error);
}
});
};
- インターフェースを呼び出し、リクエストが成功した場合、依然として localhost に対するリクエストです。