امیر اسمعیلی
امیر اسمعیلی
خواندن ۸ دقیقه·۵ سال پیش

SSR ( Server-Side Rendering ) و پیاده سازی آن در انگولار

Angular Universal
Angular Universal

تا حدود چند ماه پیش تنها کاری که سمت فرانت انجام داده بودم، چند خط html/css خیلی ناجور و دست و پا شکسته بود. تا این که سر یک پروژه ای به هر دلیلی نتونستیم کسی رو پیدا کنیم که بالاخره خودم دست به کار شدم و یکم انگولار یاد گرفتم و بقیه چیز هارو هم کم کم آماده کردم. در مورد انگولار مطالب زیادی تو اینترنت به زبان انگلیسی و فارسی هست ولی در مورد ssr که تکنیک نسبتا مهمی توی سرعت بارگزاری سایت و حتی SEO هست خیلی کم و ناقص بود، پس تصمیم گرفتم خرده چیز هایی که میدونم و فهمیدم رو به اشتراک بذارم.




اس اس آر ( SSR ) چیست ؟

امروزه که فریمورک های برنامه نویسی سمت کاربر روز به روز در حال گسترش می باشد، عمده شرکت ها و برنامه نویس ها هم برای بهینه کردن اپلیکیشن و هم بخاطر به صرفه بودن زمان به سمت فریمورک ها روی می آورند. این فریمورک ها ابزار های قدرتمندی رو به برنامه نویس ارايه میدن که این قدرتشون بخاطر JavaScript یا TypeScript ( انگولار ) هستش.

توی این فریمورک ها برنامه نویس شاید اصلا بیشتر از ده بیست خط کد js ننویسه و بیشتر کار هاشو با همون html/css انجام بده ولی !!!! اگه داخل مرورگرتون جاوا اسکریپت غیرفعال باشه، شما بدون شک جز یک صفحه سفید خالی چیز دیگه ای نخواهید دید!.

شاید بپرسید کی توی سال 2020 ( سالی که دارم می نویسم ) جاوا اسکریپت نداره؟ سوأل خیلی خوب و به جایی هستش. تقریبا همه گوشی ها سخت افزار های چندین سال اخیر جاوا اسکریپت دارن ولی بحث سر چیز دیگه ای هست. ربات ها یا Crawler ها. در واقع در حالت معمولی وقتی یک سایت لود میشه یه متن Loading ... روی صفحه ( توی انگولار اینطوریه ) نمایش داده میشه تا کاملا منابع سایت رندر بشه و وقتی تکمیل شد شما ظاهری که طراحی کرده بودید رو مشاهده می کنید. ولی بذارید اینجوری بگیم که کراولر هایی مثل گوگل / بینگ / فیسبوک / توییتر حوصله موندن توی سایت تا وقتی که جاوا اسکریپت رندر بشه رو ندارن و همون لحظه که سایت باز میشه و فرضا loading مشاهده میکنن در زمان خیلی پایین همون متن ساده رو میبینن و خارج میشن.

حالا فرض کنیم شما یک ظاهر خیلی عالی طراحی کردی یک نفر محتوا کار هم داری ولی موتور های جستجو سایت رو index نمیکنن پس کسی هم نمیبینتت پس ...

خب چیکار کنیم ؟

یکی از تکنیک ها استفاده از ssr می باشد. توی این تکنیک سایت سمت سرور کاملا رندر میشه و فایل های رندر شده رو به سمت مرورگر میفرسته. تو این حالت در همون لحظه که سایت باز میشه کاربر یا کراولر ها میتونن یک صفحه استاتیک از عنصر های html/css مشاهده کنن که باعث میشه گوگل و موتور های جستجوی دیگه بتونن محتوای سایت رو ببینن و توی لینک های داخل سایت اصطلاحا بخزن که اینجا وارد بحث SEO میشه که باعث میشه سایت شما توی نتایج گوگل / بینگ / ... بالاتر بیاد.

چجوری پیاده سازی کنیم ( انگولار 6+)

تا همین چند وقت پیش برای این کار شما باید تمام فایل هارو دستی ایجاد می کردی ولی به لطف add schematic انگولار این کار خیلی راحت ( در حد آب خوردن عرض میکنم ) شده.

اول از همه مطمئن بشید انگولار رو روی سیستمتون دارید.

$ npm install [-g] @angular/cli

خب حالا یه پروژه جدید ایجاد می کنیم.

$ ng new {project_name}
ایجاد پروژه جدید
ایجاد پروژه جدید

تو این قسمت از شما سئوال می پرسه که آیا میخواید یه ماژول دیگه برای مدیریت روت ( Route ) ها ایجاد بشه. توصیه میکنم قبول کنید. ( D: ). در مرحله بعدی نوع فایل style رو انتخاب کنید و صبر کنید تا نصب تموم بشه. خب اگه پیغام ✔ Packages installed successfully رو دیدین حله.

حالا یک آدرس جدید ایجاد میکنیم.دستور های زیر رو وارد کنید.

$ cd {project_name}
$ ng g m about --route about --module app
توضیحات مختصری در مورد سطر دوم بدم :
g : generate
m: module
توی این دستوری یک ماژول و کامپوننت جدید به اسم about با آدرس about ایجاد میشه.
شما میتونستید فقط یک کامپوننت ایجاد کنید که کفایت می کرد ولی خواستم با روش Lazy Loading هم آشنا بشید. ( توی این روش وقتی سایت بالا میاد تمامی کامپوننت ها لود نمیشن بلکه با رفتن به آدرس هر ماژول کامپوننت هاش بارگزاری میشن که سرعت اپلیکیشن رو بالا می بره.

محتوای app.component.html رو بصورت زیر تغییر بدید.

<h1>Test SSR</h1> <a routerLink=&quot/&quot>Home</a> <br> <a routerLink=&quot/about&quot>About</a> <router-outlet></router-outlet>

حالا با دستور زیاد اپلیکیشن رو اجرا کنید.

$ ng serve
صفحه ایجاد شده
صفحه ایجاد شده

صفحه ای که باید ببینید این شکلیه. حالا لطفا راست کلیک کنید و روی گزینه View page source کلیک کنید.

page source
page source

به تگ های <app-root> توجه کنید. اونجا جایی هست که تمام چیزایی که درست کردیم باید نشون داده بشه مثل همون لینک های about و home که در صفحه اول قرار دادیم. این همون جاوا اسکریپت هست که در اول مطلب بهش اشاره کردم. همونطوری که گفتم وقتی کراولر وارد سایت میشه هیچ کدوم از لینک ها و محتویات ما رو نمیبینه. ( اگه میخواین مطمئن باشید جاوا اسکریپت مرورگرتون رو خاموش بکنید. )

با دستور زیر فریمورک Universal رو به پروژه تون اضافه کنید.

$ ng add @nguniversal/express-engine --clientProject {project_name}

خب اگه پیغام ✔ Packages installed successfully رو دیدین حله.

خب وقتش رسیده نتیجه کار رو ببینیم. دستور زیر رو بزنید.

$ npm run build:ssr && npm run serve:ssr
  • توجه داشته باشید که برای مشاهده سایت بصورت ssr باید دستور بالا اجرا بشه و با ng serve به حالت Client-Side Rendering بر میگردیم.

وقتی که بیلد و اجرا تموم شد، داخل مرورگرتون به آدرس localhost:4000 برید و سایت رو مشاهده کنید. حالا اگر هم جاوا اسکریپت رو غیر فعال کنید باز هم میتونید بین لینک ها حرکت کنید و محتوای سایت رو مشاهده کنید.

توی این روش درواقع سرور شما محتویات سایت شما رو رندر میکنه و کل source سایت رو به سمت کاربر میفرسته و مرورگر دیگه موظف نیست فایل ها رو رندر کنه. حالا View page source رو دوباره بزنید.

SSR
SSR


همونطوری که مشاهده میکنید داخل تگ app-root المنت های html قابل مشاهده هستش و این صفحات مثل صفحات خالص html باهاشون برخورد میشه و این امکان رو میده که هم صفحه سریعتر لود بشه و هم توسط کراولر ها شناسایی بشیم.

  • آمار نشون میده که کاربر سایتی رو که صفحه اولش بیشتر از 3000ms طول میکشه لود شدنش،‌ با احتمال بیشتری در همون لحظات اول ترک میکنه.

معایب این تکنیک

این تکنیک مثل همه چیز معایب خودشو داره که بهتره بیان بشه.

  • چون توی این کار همه فرایند رندر سمت سرور انجام میشه امکان داره بار سنگینی به دوش سرور بیوفته و اگه سرورتون به حد تعداد درخواست ها قوی نباشه به مشکل بربخوره.
  • در این روش باید از شئ های مربوط به مرورگر مثل window, location, DOM خیلی محتاطانه استفاده بکنید. چون سرور هیچ کدوم از این هارو نمیشناسه. راه حل : سعی کنید اصطلاحا انگولاری برید جلو یعنی در حد امکان از این شئ ها استفاده نکنید ولی اگر مجبور شدید یا مثلا افزونه ای نصب کردید که به این شئ ها نیاز داشت ( مثل نقشه گوگل مپ ) اونموقع از تابع isPlatformBrowser که داخل پکیج angular/common قرار داره استفاده کنید و مشخص کنید که اگه داخل مرورگر بودیم به این شئ ها دسترسی پیدا کنه.

توصیه میکنم روش های دیگه که برای حل این مشکل وجود داره مانند prerender رو هم مطالعه کنید و همچنین شرکت هایی مثل prerender.io با قیمت کم این کار رو برای شما انجام میدن.

منابع

  1. Angular Document
  2. Ng Talks

امیدوارم این مطلب به دردتون بخوره. :)

منو دنبال کنید.

Twitter

GitHub

LinkedIn

انگولارسئوفرانتssrangular
دانشجوی مهندسی کامپیوتر و برنامه نویس فول-استک
شاید از این پست‌ها خوشتان بیاید