構(gòu)建服務(wù)器端邏輯是移動應(yīng)用開發(fā)中較為復(fù)雜的一部分。目前,React Native開發(fā)者通常需要在多個(gè)代碼庫之間切換,或者依賴第三方服務(wù)來處理服務(wù)器端邏輯。
通過將API路由直接集成到React Native項(xiàng)目中,Expo CLI和Expo Router為開發(fā)者提供了一種無縫的解決方案,減少了上下文切換,簡化了開發(fā)流程。
API路由可以通過在項(xiàng)目的app目錄中添加一個(gè)以+api.ts為后綴的新文件來創(chuàng)建。開發(fā)者可以在該文件中導(dǎo)出以下HTTP方法:GET、POST、PUT、PATCH、DELETE、HEAD和OPTIONS。當(dāng)請求的方法與導(dǎo)出的方法匹配時(shí),相應(yīng)的函數(shù)將會被執(zhí)行。
以下是一個(gè)與OpenAI安全交互的示例:
// app/generate+api.ts
import { ExpoRequest, ExpoResponse } from 'expo-router/server';
export async function POST(req: ExpoRequest): Promise {
const { prompt } = await req.json(); const json = await fetch(
'https://api.openai.com/v1/engines/text-davinci-003/completions',
{
headers: {
'Content-Type': 'application/json',
Authorization: Bearer ${process.env.OPENAI_API_KEY ?? ''},
},
method: 'POST',
body: JSON.stringify({
prompt,
max_tokens: 100,
}),
}
).then(res => res.json()); return ExpoResponse.json(json);
}
開發(fā)者可以通過.env文件安全地加載機(jī)密信息,例如:
# .env.development
OPENAI_API_KEY=xxxxxx
上述API路由文件(app/generate+api.ts)可以通過以下URL訪問:http://localhost:8081/generate。開發(fā)者可以使用npx expo啟動服務(wù),并通過以下命令發(fā)起POST請求:
$ curl -X POST -H "Content-Type: application/json"
-d '{"prompt":"Hello, my name is Evan"}'
http://localhost:8081/generate
Expo Router增強(qiáng)了本地應(yīng)用中的URL和window.location對象,支持使用相對URL進(jìn)行請求。例如:
const json = await fetch('/generate').then(res => res.json());
此外,開發(fā)者還可以通過Expo CLI的隧道支持,從公共URL提供服務(wù):
npx expo start --tunnel
一個(gè)新的包@expo/server將被引入,用于提供運(yùn)行服務(wù)器端邏輯所需的中間件和運(yùn)行時(shí)環(huán)境。
服務(wù)器端代碼將通過Expo CLI和Metro bundler進(jìn)行打包。這意味著服務(wù)器端代碼可以使用與客戶端代碼相同的語言特性。
EXPO_PUBLIC_為前綴的變量。每個(gè)API路由都會被打包成獨(dú)立文件,存儲在dist/_expo目錄中。
新的請求和響應(yīng)對象ExpoRequest和ExpoResponse將被引入。這些對象基于WinterCG規(guī)范,并包含額外的屬性以兼容Expo Router。它們的設(shè)計(jì)靈感來源于Remix、SvelteKit和Next.js 13。
以下是一個(gè)錯(cuò)誤處理的示例:
// app/blog/[post].ts
import { ExpoRequest, ExpoResponse } from 'expo-router/server';
export async function GET(request: ExpoRequest, { post }: Record) {
if (!post) {
return new ExpoResponse('No post found', {
status: 404,
headers: {
'Content-Type': 'text/plain',
},
});
}
return ExpoResponse.json({ ... });
}
Expo Router將支持在本地環(huán)境中使用相對網(wǎng)絡(luò)請求,從而簡化跨Web和原生平臺的開發(fā)。例如:
fetch('/generate');
在開發(fā)環(huán)境中,Expo會自動解析服務(wù)器地址,但在生產(chǎn)環(huán)境中,開發(fā)者需要明確指定服務(wù)器的URL。未來,開發(fā)者可以通過Expo Router配置插件在app.json中定義生產(chǎn)目標(biāo)。
與靜態(tài)模式不同,API路由支持動態(tài)路由(如app/[post].tsx),無需額外配置generateStaticParams。此外,這種模式還可以減少構(gòu)建時(shí)的工作量,加快導(dǎo)出速度。
API路由功能可以部署到大多數(shù)網(wǎng)絡(luò)托管服務(wù)商。首個(gè)Pull Request將支持Express和HTTP服務(wù)器,未來將擴(kuò)展支持更多服務(wù)商。
API路由的引入為Expo應(yīng)用提供了服務(wù)器端邏輯的強(qiáng)大支持。這不僅為開發(fā)者帶來了更高效的開發(fā)體驗(yàn),還為跨平臺身份驗(yàn)證和服務(wù)器端渲染等功能奠定了基礎(chǔ)。未來,Expo還計(jì)劃支持React服務(wù)器組件,進(jìn)一步提升開發(fā)效率。
開發(fā)者的反饋對于完善此功能至關(guān)重要。歡迎提出您的建議和意見!
原文鏈接: https://blog.expo.dev/rfc-api-routes-cce5a3b9f25d