Next 是一個 react 框架,能夠前後端一體化,用來做項目是一個不錯的選擇。本文記錄一下幾天前開發過程處理跨域問題的過程。【推薦方案二,方案二也更簡單,不過需要一點點 nodejs 基礎】
開始前請確認自己準備的跨域接口可以正常調用,如果實踐過程中出現錯誤也請先檢查接口是否正常,然後再檢查本地配置的跨域是否有錯。避免忙碌半天發現原本的接口就存在問題 :@(裝大款)
方案一:項目目錄下新建 server.js
文件,搭配 package.json scripts 啟動選項,實現開發環境跨域#
實現 >>>#
- 創建
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 發送郵件的接口,原接口地址
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 請求。
方案二:跨域接口封裝在 Next 自帶的後端 api ,前端請求封裝後的 api 實現項目跨域#
一般 Next 新建的項目下都會有
pages/api/hello.ts
這個文件,api 文件夾下也就是 Next 自帶的 nodejs 後端,在此處請求跨域接口不會觸發跨域報錯,其實也很好理解,後端就相當於本地,你的所有請求都是直接發起的,並沒用像前端那樣有自己的域名,所以也就不存在跨域問題。
如果你懂 nodejs 的話可以跳過教程了,一切都和你 nodejs 後端的用法一樣
實現 >>>#
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 前端調用接口,代碼如下
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 的請求。