وب مدرن، رابط کاربری و تجربهی وب · فصل ۱ — مرورگر، سرور، رندر و معماری صفحه · 31
صفحه چه زمانی ساخته میشود؟ Build، درخواست کاربر و مرورگر
یک همتیمی میگوید «این صفحه SSR است» و همان یک برچسب را طوری استفاده میکند که انگار همه بخشهای صفحه در یک مکان و در یک لحظه ساخته میشوند. نفر دیگری میگوید «چون بعداً JavaScript اجرا میشود، پس صفحه client-rendered است». هر دو جمله میتوانند سؤال اصلی معماری را پنهان کنند: کدام مسئولیت قبل از درخواست کاربر انجام میشود، کدام مسئولیت هنگام رسیدگی به Request، و کدام مسئولیت بعد از رسیدن Response به Browser؟
When Is a Page Built? Build Time, Request Time, and Browser Time — en-US
تا وقتی زمان و محل را نگوییم، «رندر شد» عبارت دقیقی نیست
یک همتیمی میگوید «این صفحه SSR است» و همان یک برچسب را طوری استفاده میکند که انگار همه بخشهای صفحه در یک مکان و در یک لحظه ساخته میشوند. نفر دیگری میگوید «چون بعداً JavaScript اجرا میشود، پس صفحه client-rendered است». هر دو جمله میتوانند سؤال اصلی معماری را پنهان کنند: کدام مسئولیت قبل از درخواست کاربر انجام میشود، کدام مسئولیت هنگام رسیدگی به Request، و کدام مسئولیت بعد از رسیدن Response به Browser؟
در این درس Rendering Placement Timeline v1 را میسازید. این artifact کل page را مجبور به یک label نمیکند. هر responsibility را جداگانه در BUILD_TIME، REQUEST_TIME، BROWSER_TIME یا یک مرز hybrid موجه قرار میدهد و evidence و uncertainty آن را نگه میدارد.
در پایان باید بتوانید درباره timing صحبت کنید بدون اینکه واژههایی مثل SSR، CSR، static، dynamic یا hydration را جایگزین responsibility map کنید.
فقط دو boundary لازم را از درسهای قبل حمل کنید
WEBF-001 prerequisite سخت است: boundary مربوط به Request/Response میان Browser و server را نگه دارید. WEBF-003 prerequisite نرم است: تفاوت response ازپیشتولیدشده با responseی که از context فعلی Request/server ساخته میشود را نگه دارید.
مالکیت این صفحه فقط rendering و generation timing در split-canonical مدل WEB-000 است. این درس framework آموزش نمیدهد، performance ranking عمومی نمیسازد، WEB-000 را نمیبندد و ادعا نمیکند هر page فقط یک rendering time دارد.
سه محل زمانی بسازید و بعد hybrid را مجاز بدانید
مدل حداقلی سه محل برای responsibility دارد.
Build time — قبل از Request مشخص کاربر. یک فرایند build یا deployment میتواند source content، data یا template را قبل از ورود traffic به artifact تبدیل کند. اگر Request بعدی همان artifact ازقبلتولیدشده را دریافت کند، responsibility تولید آن artifact قبل از Request انجام شده است. این فقط placement زمانی است؛ به معنی «این page دیگر هرگز تغییر نمیکند» نیست.
Request time — بعد از رسیدن Request و قبل از ارسال Response. server-side application میتواند Request یا data فعلی سمت server را بررسی کند و representation مربوط به Response را هنگام request handling بسازد. MDN همین boundary تولید request/response را برای dynamic site توضیح میدهد. [S-MDN-CS]
Browser time — بعد از رسیدن Response به Browser. Browser، HTML و resourceهای مرتبط را پردازش میکند تا page نمایش داده شود و client-side code میتواند بعد از delivery رفتار را فعال یا update کند. در React، hydrateRoot یک مثال vendor-specific است که در آن logic سمت client به HTML تولیدشده در server متصل میشود؛ این مثال requirement عمومی برای همه browser renderingها نیست. [S-MDN-CS] [S-REACT-HYDRATE]
یک feature میتواند هر سه محل را همزمان داشته باشد. پس مدل responsibilityها را classify میکند، نه کل page را.
responsibility، trigger و uncertainty را ثبت کنید
Rendering Placement Ledger جدول row-level داخل artifact اصلی یعنی Rendering Placement Timeline v1 است و artifact دوم محسوب نمیشود. برای هر concern محدودشده این fieldها را ثبت کنید:
- Observed fact/requirement: چیزی که scenario واقعاً میگوید.
- Responsibility: چیزی که باید produce، select، render، activate یا update شود.
- Placement: یکی از
BUILD_TIME،REQUEST_TIME،BROWSER_TIME،HYBRIDیاUNKNOWN. - Trigger/input: build/deployment input، request data، current server state، browser state، user interaction یا علت صریح دیگر.
- Rationale: چرا evidence این placement را پشتیبانی میکند.
- Uncertainty/constraint: چه چیزی هنوز معلوم نیست یا چه شرطی placement را باطل میکند.
- Next evidence: قبل از claim قویتر چه چیزی باید بررسی شود.
دو سؤال جلوی category collapse را میگیرند: این responsibility چه زمانی اطلاعات کافی برای اجرا دارد؟ و این اطلاعات در کجا در دسترس میشود؟
generation time و display time مرتبطاند اما یکی نیستند
Build-time generation یعنی «غیرتعاملی» نیست
یک HTML shell میتواند قبل از traffic تولید شود و بعد از delivery، JavaScript رفتار browser-side اضافه کند. تولید shell و رفتار بعدی Browser دو row متفاوت در timeline هستند.
Request-time generation یعنی «همیشه تازهتر» نیست
server میتواند representation را هنگام Request بسازد ولی از input کششده، delayed یا stale استفاده کند. Freshness به data و invalidation path بستگی دارد، نه فقط به لحظه اجرای template. در این درس freshness requirement را constraint ثبت میکنیم، نه قانون عمومی.
Browser-time rendering یعنی server هیچ کاری نکرده نیست
حتی اگر server ابتدا HTML را تولید کرده باشد، Browser همان document برگشتی را برای نمایش پردازش میکند. Hydration در React این separation را واضح میکند: server-generated HTML وجود دارد و سپس client logic در Browser attach میشود. [S-REACT-HYDRATE]
SSR و CSR میتوانند responsibilityهای mixed را پنهان کنند
ممکن است یک page یک shell را قبل از traffic بسازد، یک fragment محدود را هنگام Request محاسبه کند و یک interactive state جدا را در Browser فعال کند. Acronym میتواند shorthand مفیدی در یک stack مشخص باشد، اما decision record هنوز باید هر responsibility و evidence آن را جدا قرار دهد.
contrast caseها، بدون تبدیل label به قانون
Case 1 — release note ساختهشده هنگام deployment
release note در deployment تولید و تا release بعدی همان artifact سرو میشود. document generation را در build time قرار دهید. وقتی کاربر page را باز میکند، Browser همچنان document برگشتی را در browser time پردازش و نمایش میدهد. از این نتیجه نگیرید که build-time یعنی «Browser کاری ندارد».
Case 2 — shipping estimate مخصوص Request
shipping estimate به destination و inventory state موجود هنگام request handling وابسته است. اگر این inputها باید روی Response اثر بگذارند، estimate generation را در request time قرار دهید. این evidence نمیگوید بقیه page هم باید request-time باشد.
Case 3 — disclosure control فقط داخل Browser
Response از قبل article text و disclosure بسته را دارد. click کاربر فقط displayed state را محلی عوض میکند. interaction/update را در browser time قرار دهید. این placement بهتنهایی چیزی درباره زمان تولید HTML اولیه ثابت نمیکند.
Guided realistic case — product page
shell قبل از traffic ساخته میشود، price برای هر Request محاسبه میشود و wishlist state در Browser فعال میشود. model answer را کپی نکنید. سه row در Rendering Placement Timeline v1 بسازید، placement هرکدام را justify کنید و یک مورد بنویسید که scenario هنوز آن را ثابت نمیکند.
دو misconception مسدودکننده
Failure 1: «Rendering یا روی server است یا داخل Browser.» این جمله چند responsibility را در یک event فشرده میکند. repair: generation representation را از browser processing/activation جدا کنید و چند row را مجاز بدانید.
Failure 2: «Build-time output برای همیشه stale است.» Build-time generation فقط زمان تولید artifact را میگوید؛ نمیگوید regeneration، Request بعدی یا browser update هرگز ممکن نیست. repair: update mechanism و freshness constraint را جدا ثبت کنید.
هشدار مرتبط: hydration synonym عمومی browser rendering نیست. hydrateRoot در React یک operation مشخص روی server-generated HTML است. آن را مثال boundary بدانید، نه تعریف همه browser-time renderingها. [S-REACT-HYDRATE]
زبان architecture review که با عوضشدن framework نمیشکند
بهجای page-wide label یک statement محدودشده بسازید:
«shell راهنمای رویداد هنگام deployment تولید میشود؛ request-time work یک notice مخصوص کاربر واردشده را از session state فعلی انتخاب میکند؛ browser-time work بعد از delivery جزئیات session را با data از قبل تحویلشده باز میکند. این placement فقط تا وقتی معتبر است که guide بتواند تا deployment بعدی صبر کند، notice باید داخل Response اولیه باشد و expansion به server data جدید نیاز نداشته باشد.»
ارزش statement در wording نیست؛ در این است که responsibility، timing، input و invalidation condition را مشخص میکند. با تغییر framework هنوز reasoning قابل review میماند.
در review حرفهای چهار دسته را جدا نگه دارید: observed fact، design/inference، uncertainty و non-claim. نام stack باید بعد از timing decision بیاید، نه بهجای آن.
placement را برای هر responsibility انتخاب کنید
Build time مناسب است وقتی input لازم قبل از Request در دسترس است و freshness window اجازه pre-production میدهد. این انتخاب میتواند request-path work را کم کند ولی مسئولیت rebuild یا invalidation ایجاد کند.
Request time مناسب است وقتی خود Response باید current request/server context را منعکس کند و نمیتوان آن کار را safely عقب انداخت. این placement contextual generation میدهد ولی work و dependency را وارد request path میکند.
Browser time مناسب است وقتی responsibility به browser-local state یا interaction بعد از delivery وابسته است، یا product عمداً آن کار را defer میکند. این placement میتواند coupling سمت server را برای همان concern کم کند ولی به client capability وابسته است و ممکن است بعد از initial content رخ دهد.
HYBRID را برای یک row فقط وقتی بهکار ببرید که همان responsibility محدود واقعاً از بیش از یک timing boundary عبور کند و شکستن آن به چند row، claim مورد بررسی را از بین ببرد. اگر responsibilityهای متفاوت placementهای متفاوت دارند، feature mixed است اما این بهتنهایی مجوز HYBRID برای هر row نیست؛ responsibilityها را جدا کنید. Hybrid راه فرار نیست و row هیبرید هنوز باید boundaryهای عبورشده، rationale، uncertainty و next evidence را ثبت کند.
scaffold را کم کنید
Guided pass: این سه responsibility را جدا classify کنید: navigation shell ساختهشده در deployment، access message انتخابشده از current account permission هنگام Request، و tab switch بعد از click داخل Browser.
Less-guided pass: labelهای timing را حذف کنید. برای هر responsibility اول بنویسید decisive input چه زمانی در دسترس میشود و بعد placement را انتخاب کنید.
Independent pass: scenario product page در Bible را حل کنید: shell قبل از traffic، price per request، wishlist activation در Browser. record را بدون استفاده از SSR/CSR بهعنوان rationale کامل کنید. حداقل دو non-claim و یک evidence که میتواند placement را تغییر دهد اضافه کنید.
اگر evidence کافی نیست، UNKNOWN placement موقت معتبر است. حدسزدن معتبر نیست.
evidence کافی چه شکلی است؟
یک record reviewable اجازه میدهد فرد دیگری reasoning شما را بازسازی کند:
| responsibility | observed fact/requirement | placement | trigger/input | rationale | uncertainty / constraint | next evidence |
|---|---|---|---|---|---|---|
| یک concern محدود | چیزی که scenario میگوید | build / request / browser / hybrid / unknown | decisive input چه زمانی/کجا میآید | علت placement | چیزی که ثابت نشده | بررسی بعدی |
Rendering Placement Timeline v1 نهایی باید non-claim صریح داشته باشد و نباید مالک کل canonical WEB-000 یا chapter exit شود. executable coding Lab لازم نیست؛ construct این درس responsibility placement و architecture judgment است، نه implementation syntax.
Assessment و transfer
پنج نوع evidence سنجیده میشود:
- Retrieval: build time، request time و browser time را جدا کنید و یک non-claim بنویسید.
- Application: responsibilityهای مستقل یک feature mixed جدید را place کنید.
- Diagnosis: page-wide timing claimی را repair کنید که server generation و browser work را collapse کرده است.
- Decision: bounded placement انتخاب کنید و uncertainty و invalidation evidence را ثبت کنید.
- Transfer: Rendering Placement Timeline v1 را برای product pageای کامل کنید که shell آن قبل از traffic ساخته میشود، price برای هر Request محاسبه میشود و wishlist state در Browser فعال میشود.
Diagnosis، decision و transfer blocking هستند. acronym مربوط به stack بهتنهایی evidence نیست. پاسخ باید timing، responsibility، rationale، uncertainty و non-claim را قابلبررسی کند.
sourceهای اعلامشده و freshness boundary
این درس فقط دو source منجمدشده در Bible را استفاده میکند:
- S-MDN-CS — MDN Client-server overview: request/response processing و server-side generation boundary.
- S-REACT-HYDRATE — React
hydrateRoot: یک مثال vendor-current از attach شدن client logic به server-generated HTML؛ نه requirement عمومی rendering.
هر دو source در 2026-09-10 دوباره بررسی شدند و boundary لازم هنوز با Bible سازگار است. source set گسترش پیدا نکرد. review بعدی حداکثر تا 2026-12-31 یا زودتر در صورت تغییر vendor/framework terminology یا صفحه مرجع لازم است.
مرز نهایی: این درس نمیگوید page دقیقاً یک rendering time دارد، build-time output نمیتواند interactive شود یا request-time rendering همیشه تازهتر یا بهتر است.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
WEBF-004-SUM1 retrieval
Build time، request time و browser time را با یک responsibility مناسب برای هرکدام از هم جدا کنید. سپس یک non-claim بنویسید که مانع تبدیل مدل به page-wide label شود.
WEBF-004-SUM2 application
یک conference page، schedule shell را در deployment از قبل تولید میکند، access notice مخصوص attendee را هنگام Request انتخاب میکند و session detail را بعد از click داخل Browser باز میکند. سه responsibility را جدا place کنید و decisive input هرکدام را بنویسید.
WEBF-004-SUM3 diagnosis
متن یک help article از قبل داخل HTML برگشتی وجود دارد. بعد از load، یک script داخل Browser از scroll position کاربر reading progress را محاسبه میکند. یک همتیمی progress calculation را فقط به این دلیل که HTML از server آمده `REQUEST_TIME` میزند. خطای timing را diagnosis کنید و مدل را به rowهای جدا بازنویسی کنید و evidence تعیینکننده هر row را بنویسید.
WEBF-004-SUM4 decision
index یک course catalog میتواند هر شب rebuild شود. enrollment availability باید داخل Response اولیه باشد و data آن بیش از ۳۰ ثانیه قدیمی نباشد، اما هنوز نمیدانید server cache بهاندازه کافی تازه هست یا نه. font-size preference فقط local Browser است. برای هر سه responsibility placement محدود انتخاب کنید، هر شرط `UNKNOWN` را حفظ کنید و بنویسید چه evidenceای تصمیم availability را تغییر میدهد.
WEBF-004-SUM5 transfer
Rendering Placement Timeline v1 را برای product pageای کامل کنید که shell آن قبل از traffic ساخته میشود، price برای هر Request محاسبه میشود و wishlist state در Browser فعال میشود. rowهای responsibility را جدا کنید و trigger/input، rationale، حداقل دو non-claim، uncertainty و evidenceی که میتواند placement را تغییر دهد ثبت کنید.
ملاکهای ارزیابی (rubric)
Critical dimensions:
- Boundary correctness: build-time generation, request-time generation, and browser-time processing/activation are separated by responsibility; a page-wide label is not accepted as a substitute for row evidence.
- Hybrid discipline:
HYBRIDis valid for a row only when the same bounded responsibility genuinely crosses more than one timing boundary and cannot be honestly decomposed; different responsibilities with different placements must normally be separate rows. - Claim boundedness: vendor-specific hydration is not generalized into a universal browser-rendering rule; freshness/performance claims remain conditional.
- Decision justification: each placement follows from stated inputs/timing constraints, preserves
UNKNOWNwhen evidence is missing, and records what evidence would invalidate or revise the placement. - Blocking diagnosis: SUM3 must reject the inference that server delivery makes a browser-local scroll computation request-time and must avoid inventing the original article generation timing.
- Decision scenario: SUM4 must keep the availability/cache uncertainty explicit until evidence closes it.
- Transfer: SUM5 must contain all required Rendering Placement Timeline v1 row/final fields, at least two non-claims, and independent reasoning for the reserved product-page scenario.
Blocking failure remains if the final record says rendering must occur only on server or browser, treats HYBRID as a catchall, claims build-time output is inherently forever stale, invents missing freshness evidence, or reproduces the transfer answer from a supplied model.
منابع و تازگی
مطالعهٔ موارد (case studies)
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)