ایجاد برنامه های Jamstack در وب چالش بزرگی وجود دارد. در این مقاله، Caleb Olojo توضیح می دهد که چگونه می توانید از Next.js برای بوت استرپ ایمن برنامه خود استفاده کنید.
توسعه دهندگان فرانت اند باید با API های خصوصی یا عمومی که روش مجوز آنها به یک کلید مخفی/کلید API نیاز دارد که توسعه دهندگان را قادر می سازد از این API ها استفاده کنند، تعامل داشته باشند. کلید(های) مهم هستند، از این رو نیاز به ذخیره/حفاظت از کلید(ها) بوجود می آید. ایجاد یک متغیر محیطی که کلید را ذخیره میکند، راهحلی است که بیشتر توسعهدهندگان از آن استقبال میکنند، اما یک نکته وجود دارد. متغیر محیطی از کلید(های) محافظت نمی کند از هر کسی که راه خود را در مورد ابزارهای توسعه دهنده مرورگر خود می داند. به همین دلیل است که وقتی در حال نوشتن تماس های API خود هستیم، باید از کلیدهای خود در سمت سرور استفاده کنیم.
در این مقاله، ما از Next.js برای بوت استرپ برنامه خود استفاده خواهیم کرد. این بدان معنا نیست که create-react-app
کتابخانه کار نخواهد کرد می توانید از هر کدام که راحت می دانید استفاده کنید. ما از Next.js به دلیل مزایای زیادی که به همراه دارد استفاده می کنیم. (می توانید درباره Next.js بیشتر بخوانید اینجا.)
اجازه دهید با نصب وابستگی هایی که در این پروژه نیاز داریم شروع کنیم. ما با ایجاد یک برنامه Next.js شروع می کنیم. دستور زیر این کار را برای ما انجام می دهد:
npx create-next-app [name-of-your-app]
ما از جاوا اسکریپت بومی استفاده خواهیم کرد "Fetch API"
کتابخانه برای دریافت داده از API. ما در این مقاله خیلی از جنبه های ظاهری را پوشش نمی دهیم. (اگر می خواهید به پروژه نمونه ای که من با استفاده از الگوی مسیر Next.js API ساخته ام نگاهی بیندازید، می توانید مخزن را پیدا کنید. اینجا.)
حال بیایید نگاهی به ساختار فایل برنامه بیندازیم. ما بر روی فایل های مهم مورد نیاز در این برنامه تمرکز خواهیم کرد، بنابراین مختصر خواهد بود.
|--pages
| |-- api
| | |-- serverSideCall.js
| |-- _app.js
| |-- index.js
|__ .env.local
تفکیک فایل ها در ساختار برنامه
در این قسمت فایل های مختلف تشکیل دهنده معماری این پروژه و عملکردهای مربوط به آنها را در زیر مشاهده می کنیم.
در pages
دایرکتوری جایی است که تمام مسیریابی برنامه انجام می شود. این یک ویژگی خارج از جعبه Next.js است. از استرس سخت کدگذاری مسیرهای مستقل شما جلوگیری می کند.
-
pages/api
دایرکتوری api به شما این امکان را می دهد که به جای روش معمول ایجاد مخازن جداگانه برای API های REST یا GraphQL خود و استقرار آنها در پلتفرم های میزبانی پشتیبان مانند Heroku و غیره، یک Backend برای برنامه Next.js خود، در داخل همان پایگاه کد داشته باشید.با
api
دایرکتوری، هر فایل به عنوان یک نقطه پایانی API در نظر گرفته می شود. اگر بهapi
پوشه، متوجه خواهید شد که ما یک فایل به نام داریمuser.js
در آنآن فایل به نقطه پایانی تبدیل می شود، به این معنی که یک فراخوانی API را می توان با استفاده از مسیر فایل به عنوان URL پایه انجام داد.
const getData = async() => {
fetch("/api/users")
.then(response => response())
.then(response => console.log(response.data))
.catch(err => console.log(err)
}
pages/_app.js
جایی است که تمام اجزای ما به DOM متصل می شوند. اگر به ساختار کامپوننت نگاهی بیندازید، خواهید دید که تمام اجزا به عنوان ارسال می شوندpageProps
بهComponent
لوازم جانبی نیز
function MyApp({ Component, pageProps }) {
return (
<React.Fragment>
<Head>
<meta name="theme-color" content="#73e2a7" />
<link rel="icon" type="image/ico" href="" />
</Head>
<Component {...pageProps} />
</React.Fragment>
);
}
export default MyApp;
اگر با Next.js تازه کار هستید، لطفاً این مقاله را دنبال کنید تا شما را در این فرآیند راهنمایی کند.
index.js
این مسیر پیش فرض در پوشه pages است. هنگامی که دستور زیر را اجرا می کنید، سرور توسعه و محتویات آن را راه اندازی می کندindex.js
در صفحه وب ارائه می شوند.
npm run dev
.env.local
این جایی است که ما کلید API را ذخیره می کنیم که به ما امکان می دهد این API را مصرف کنیم.
فراخوانی API سمت سرور
بخش قبلی شما را در معرض فایل هایی قرار داد که با آنها تعامل خواهیم داشت و عملکردهای خاص آنها. در این بخش به نحوه مصرف API می پردازیم.
دلیل اینکه ما در حال نوشتن فراخوانی API در سمت سرور هستیم، ایمن کردن کلید API خود است و Next.js در حال حاضر این کار را برای ما آسان کرده است. با مسیرهای API در Next.js، میتوانیم تماسهای API خود را بدون ترس از آشکار شدن کلیدهای API در سمت کلاینت انجام دهیم.
ممکن است از خود پرسیده باشید که جوهر متغیر محیطی در چیست .env
فایل است، در این سناریو.
متغیر محیطی (که کلید API ما است) فقط می تواند در دسترس باشد development
حالت
به همین دلیل است که ما می توانیم کاری مشابه انجام دهیم process.env.api_key
و به متغیر محیطی دسترسی پیدا کنید.
اما، لحظه ای که برنامه خود را روی پلتفرم هایی مانند Netlify یا Vercel مستقر می کنید، حالت به تغییر می کند production
، که Node.js را می سازد process
شی در سمت مشتری در دسترس نیست.
اکنون که دلیل نیاز به نوشتن یک فراخوانی API سمت سرور را دیدید. بیایید فوراً به آن برسیم.
export default async function serverSideCall(req, res) {
const {
query: { firstName, lastName },
} = req;
const baseUrl = `https://api.example-product.com/v1/search?
lastName=${lastName}&firstName=${firstName}
&apiKey=${process.env.KEY}
`;
const response = await fetch (baseUrl);
res.status(200).json({
data: response.data,
});
}
در قطعه بالا، یک تابع ناهمزمان ایجاد کردیم به نام: serverSideCall
. این در دو استدلال می گیرد، req
که مخفف “درخواست” به طور کامل است، و res
که به طور کامل “پاسخ” است.
در req
آرگومان دارای برخی ویژگی ها است (یا به قول اسناد Next.js “middleware”) که زمانی که ما API خود را مصرف می کنیم می توان به آنها دسترسی داشت، یکی از آنها این است. req.query
.
متوجه خواهید شد که ما آن را تخریب کردیم query
ویژگی موجود در قطعه بالا، بنابراین اکنون باید بتوانیم آن متغیرها را به عنوان مقادیر به خصوصیات query نقطه پایانی API منتقل کنیم. در زیر به آن نگاهی بیندازید.
توجه داشته باشید: میتوانید درباره میانافزارهای داخلی که همراه با آنها ارائه میشوند، اطلاعات بیشتری کسب کنید req
بحث و جدل اینجا.
const {
query: { firstName, lastName },
} = req;
URL پایه خصوصیات پرس و جوی تخریب شده را به عنوان مقادیر و apiKey
از .env
فایل از طریق Node.js process
هدف – شی.
خصوصیات پرس و جوی ساختاریافته به عنوان درخواست هایی در نظر گرفته می شوند که از مقادیر ورودی مؤلفه فرم (که در بخش بعدی ایجاد خواهیم کرد) به API ارسال می شوند، پس از دریافت، پاسخی مطابق با درخواست دریافت می کنیم. ما درست کردیم، ما ساختیم.
const baseUrl = `https://api.kelvindata.com/rest/v1/searchv2? lastName=${lastName}&firstName=${firstName}&apiKey=${process.env.KEY}`;
فرآیند بعدی که تابع باید تکمیل کند، پاسخ از فراخوانی API ناهمزمان است. قطعه زیر تماس API را که با آن انجام میدهیم اختصاص میدهد axios
کتابخانه به یک متغیر، response
.
در خط بعدی، res
آرگومان از status
روشی که برای ارسال پاسخ JSON به ما استفاده می شود، سپس می توانیم متغیر پاسخ را به عنوان یک ویژگی اختصاص دهیم data
.
const response = await axios.get(baseUrl);
res.status(200).json({
data: response.data,
});
میتوانید درباره کدهای مختلف وضعیت HTTP اطلاعات بیشتری کسب کنید اینجا.
استفاده عملی از عملکرد API سمت سرور
در این بخش، نگاهی به نحوه استفاده از فراخوانی API سمت سرور با ایجاد فرمی با دو فیلد ورودی خواهیم داشت. مقادیر ورودی به عنوان پارامترهای پرس و جو به نقطه پایانی API ارسال می شود.
import React from "react";
const Index = () => {
const [data, setData] = React.useState([]);
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");
const getuserData = async () => {
// api call goes here
};
const handleSubmit = (e) => {
e.preventDefault();
getuserData();
};
return (
<React.Fragment>
<form onSubmit={handleSubmit}>
<label htmlFor="firstname">First name</label>
<input
type="text"
name="firstname"
value={firstName}
placeholder="First Name"
onChange={(e) => setFirstName(e.target.value)}
/>
<label htmlFor="lastname">Lastname</label>
<input
type="text"
name="lastname"
value={lastName}
placeholder="Lastname"
onChange={(e) => setLastName(e.target.value)}
/>
<button>Search</button>
</form>
<div className="results-from-api"></div>
</React.Fragment>
);
};
export default Index;
از آنجایی که این یک جزء React است که دادهها را از یک نقطه پایانی API دریافت میکند، باید یک حالت داخلی خودش را داشته باشد. قطعه زیر نشان می دهد که چگونه متغیرهای حالت مختلف را با React Hooks تعریف کردیم.
const [userData, setUserData] = React.useState([]);
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");
در firstName
و lastName
متغیرها مقادیر متنی را که توسط هر کسی در فیلد ورودی تایپ می شود را در متغیرهای حالت محلی ذخیره می کند.
در data
متغیر state به ما کمک می کند پاسخی را که از فراخوانی API دریافت می کنیم در یک آرایه ذخیره کنیم، بنابراین می توانیم از جاوا اسکریپت استفاده کنیم. map()
روش ارائه پاسخ در صفحه وب
در زیر، ما استفاده می کنیم axios
برای دریافت داده از نقطه پایانی API. اما در اینجا، URL پایه معمولی نیست https://
URL، در عوض، مسیر فایلی است که قبلاً تماس API سمت سرور را انجام داده بودیم.
const getuserData = async () => {
fetch(`/api/usersfirstName=${firstName}&lastName=${lastName}`, {
headers: {
Accept: "application/json",
},
})
.then((response) => response)
.then((response) => {
setData(response.data.data);
console.log(response.data.data);
})
.catch((err) => console.log(err));
};
همین روند در serverSideCall.js
فایل تکرار می شود، اما این بار با هدرهای API لازم واکشی و تخصیص متغیرهای حالت ورودی به پارامترهای پرس و جوی API.
نتیجه
رویکردهای دیگری نیز وجود دارد که می تواند به دستیابی به این شاهکار کمک کند. در اینجا به برخی از آنها اشاره می کنیم:
- ایجاد توابع Netlify Lambda که به محافظت از کلیدهای API شما در سمت سرویس گیرنده کمک می کند.
این روش تقریباً این کار را برای شما انجام می دهد، اما اگر طرفدار نوشتن کدهای زیادی نیستید، به شما کمک می کند کارهای کوچک را انجام دهید. مسیر Next.js API بهترین گزینه برای حل این مشکل است. - ارائه سرور با Next.js برای پنهان کردن کلیدهای API.
در این ویدئو، ایجما اونوزولیکه توضیحی در مورد چگونگی انجام این کار با رندر سمت سرور ارائه می دهد. توصیه می کنم آن را بررسی کنید.
برای خواندن این مقاله از شما تشکر می کنم. لطفاً آن را به اشتراک بگذارید و همچنین با خیال راحت به یک پروژه مثال عملی که با استفاده از مسیر Next.js API ساختهام نگاهی بیندازید. اینجا.
خواندن بیشتر در مجله Smashing
