Skip to main content
Trang này đặc tả Inertia protocol: wire contract chính xác giữa Inertia client và server của bạn. Hãy đọc trang cách hoạt động trước để có cái nhìn tổng quan. Protocol không phụ thuộc framework. Bất kỳ backend nào giao tiếp qua HTTP đều có thể triển khai protocol này, vì vậy bạn có thể xây dựng server-side adapter mới bằng bất kỳ ngôn ngữ nào. Laravel adapter chính thức được dùng làm implementation tham chiếu xuyên suốt trang này, và mọi request/response bên dưới đều là ví dụ thực tế có thể copy-paste.

Response HTML

Request đầu tiên đến một ứng dụng Inertia chỉ là request trình duyệt tải toàn bộ trang thông thường, không có header hoặc dữ liệu đặc biệt nào của Inertia. Với các request này, máy chủ trả về một tài liệu HTML đầy đủ. HTML response này bao gồm asset của site (CSS, JavaScript) cùng một <div> root trong phần body. <div> root đóng vai trò mounting point cho ứng dụng phía client. Một phần tử <script type="application/json"> chứa page object được mã hóa JSON cho trang ban đầu. Inertia dùng thông tin này để khởi động client-side framework và hiển thị page component đầu tiên.
Page object nhúng được in bên trong thẻ <script>, vì vậy JSON đã serialize BẮT BUỘC phải escape mọi dấu gạch chéo (/ thành \/), đó là lý do ví dụ trên chứa "\/events\/80". Điều này ngăn chuỗi </script> nằm trong dữ liệu prop đóng thẻ script quá sớm và làm hỏng trang. KHÔNG ĐƯỢC dùng HTML entity encoding ở đây vì trình duyệt không decode entity bên trong script body, khiến việc parse JSON thất bại.

Response Inertia

Sau khi ứng dụng Inertia được khởi động, mọi request tiếp theo đến website đều được thực hiện qua XHR với header X-Inertia đặt thành true. Header này cho biết request được thực hiện bởi Inertia và không phải một lần tải toàn bộ trang thông thường. Server phát hiện header X-Inertia và trả JSON response chứa page object đã mã hóa thay vì trả toàn bộ tài liệu HTML.

Sơ đồ lifecycle của request

Sơ đồ dưới đây minh họa vòng đời request trong một ứng dụng Inertia. Lần truy cập đầu tạo request thông thường tới server, server trả về khung HTML của ứng dụng chứa root element cùng dữ liệu đã hydrate. Với các tương tác và điều hướng tiếp theo, Inertia gửi XHR request nhận về JSON. Inertia dùng response này để hydrate động và thay page component mà không cần full-page reload.

Cách client xử lý response

Sau mỗi request, client kiểm tra response trước khi thay đổi trang. Luồng xử lý tuân theo một số quy tắc nhỏ:
  • Inertia response (X-Inertia: true) được render trực tiếp: client áp dụng page object và thay component.
  • 409 ConflictX-Inertia-Location kích hoạt full visit bằng window.location tới URL đó để tải asset mới. Background request được miễn khi version thay đổi, vì reload một visit mà người dùng chưa từng khởi tạo sẽ làm mất state chưa lưu.
  • 409 ConflictX-Inertia-Redirect kích hoạt một Inertia GET visit mới tới URL đó.
  • Mọi response khác, chẳng hạn tài liệu HTML, JSON thông thường hoặc trang lỗi, được xem là exception. Client phát một HTTP exception event có thể hủy và, trừ khi bạn hủy event, hiển thị error modal thay vì âm thầm điều hướng.
Các redirect 3xx tiêu chuẩn không đi qua những quy tắc này. Trình duyệt tự động theo redirect và gửi lại request header đến location mới, vì vậy X-Inertia đến được redirect target và client chỉ kiểm tra response cuối cùng trong chuỗi. Xem redirects để biết các status server dùng để điều khiển luồng này. Một Inertia response hợp lệ có status 400 trở lên cũng phát cùng HTTP exception event có thể hủy trước khi render. Nếu hủy event ở đây, việc render bị chặn để bạn tự xử lý lỗi.

Request header

Các header sau được Inertia tự động gửi khi thực hiện request. Bạn không cần thiết lập thủ công; client-side adapter của Inertia sẽ xử lý chúng.
boolean
Đặt thành true để chỉ ra đây là request Inertia.
string
Được đặt thành XMLHttpRequest trong mọi request Inertia.
string
Đặt thành text/html, application/xhtml+xml để cho biết các kiểu response được chấp nhận.
string
Đặt thành application/json cho request không chứa file upload.
string
Phiên bản asset hiện tại dùng để kiểm tra asset mismatch.
string
CSRF token được đọc từ cookie XSRF-TOKEN. Tên cookie và header có thể cấu hình.
string
Đặt thành prefetch khi thực hiện request prefetch.
string
Tên component dành cho partial reload.
string
Danh sách props cần đưa vào partial reload, phân tách bằng dấu phẩy.
string
Danh sách props cần loại khỏi partial reload, phân tách bằng dấu phẩy.
string
Danh sách props cần reset khi điều hướng, phân tách bằng dấu phẩy.
string
Đặt thành no-cache cho request reload để tránh phục vụ nội dung đã cũ.
string
Chỉ định error bag dùng cho validation error.
string
Cho biết dữ liệu được yêu cầu nên append hay prepend khi dùng Infinite scroll.
string
Danh sách phân tách bằng dấu phẩy gồm các key once prop chưa hết hạn và đã được tải ở client. Server sẽ bỏ qua việc resolve các prop này trừ khi chúng được yêu cầu rõ ràng qua partial reload hoặc được force refresh ở phía server.
Các header sau được dùng cho request validation bằng Precognition.
boolean
Đặt thành true để cho biết đây là request validation Precognition.
string
Danh sách tên field cần validation, phân tách bằng dấu phẩy.

Response header

Các header sau được đặt trên Inertia JSON page response. Server-side adapter chính thức tự động xử lý chúng.
boolean
Đặt thành true để cho biết đây là response Inertia.
string
Đặt thành X-Inertia để giúp trình duyệt phân biệt chính xác giữa response HTML và JSON.
Các header sau xuất hiện trên control response 409 Conflict thay vì page response. Response 409 không mang header X-Inertia vì nó yêu cầu client điều hướng thay vì render trang.
string
URL đích cho full visit bằng window.location. Được đặt trên external location visit và khi reload do asset version không khớp.
string
URL redirect đầy đủ, bao gồm fragment, dành cho redirect có target chứa URL fragment. Kích hoạt một Inertia GET visit mới thay vì full-page reload.
string
Asset version hiện tại, được echo trong response 409 do version không khớp để client có thể quan sát giá trị đó.
Các header sau được dùng cho response validation bằng Precognition.
string
Đặt thành true để cho biết đây là response validation Precognition.
string
Đặt thành true khi validation thành công và không có lỗi, kết hợp với status 204 No Content.
string
Đặt thành Precognition trên mọi response khi middleware Precognition được áp dụng.

Page object

Inertia chia sẻ dữ liệu giữa server và client thông qua page object. Object này chứa thông tin cần thiết để render page component, cập nhật history state của trình duyệt và theo dõi asset version của site. Page object có thể bao gồm các thuộc tính sau:
string
Tên của page component JavaScript.
object
Các page prop. Chứa toàn bộ dữ liệu của trang cùng object errors (mặc định là {} nếu không có lỗi).
string
URL của trang.
string|number
Asset version hiện tại.
boolean
mã hóa history state của trang hiện tại hay không. Chỉ được đưa vào khi là true.
boolean
Có xóa encrypted history state hay không. Chỉ được đưa vào khi là true.
boolean
giữ URL fragment của request ban đầu qua redirect hay không.
array
Mảng các key prop cần được gộp (append) trong quá trình điều hướng.
array
Mảng các key prop cần được prepend trong quá trình điều hướng.
array
Mảng các key prop cần được deep merge trong quá trình điều hướng.
array
Mảng các key prop dùng để khớp phần tử khi gộp prop.
object
Cấu hình hành vi gộp prop cho infinite scroll. hành vi merge.
object
Cấu hình cho việc lazy-load prop phía client.
array
Mảng key deferred prop không resolve thành công và đã được rescue phía server. Client dùng danh sách này để render slot rescue trên component <Deferred>.
array
Mảng key prop cấp cao nhất được đăng ký qua Inertia::share(). Client dùng chúng để mang shared prop sang trong instant visit.
object
Cấu hình cho once props, là các prop chỉ nên được resolve một lần rồi tái sử dụng ở các trang sau. Mỗi entry ánh xạ một key tới object chứa tên prop và timestamp expiresAt tùy chọn (tính bằng millisecond).
object
Flash session data của request hiện tại. Chỉ được đưa vào khi có flash data. Client cung cấp dữ liệu này qua event inertia:flash và loại bỏ nó khỏi history state được lưu bền vững.
Chỉ component, props, urlversion luôn có mặt trên mọi page object, vì vậy một page object tối thiểu có dạng sau:
Các field metadata còn lại là có điều kiện, chỉ được phát ra khi hành vi prop tương ứng áp dụng. Field vắng mặt mặc định ở client thành mảng rỗng, object rỗng hoặc false, vì vậy server có thể bỏ field rỗng hoặc phát rõ field đó mà kết quả vẫn tương đương.

Mô hình đánh giá prop

Mỗi prop server trả về thuộc một hoặc nhiều nhóm. Nhóm đó quyết định prop có được resolve cho request cụ thể hay không và page object mang metadata nào, nếu có, để mô tả nó. Các quy tắc này hoàn toàn là vấn đề resolve ở phía server; client chỉ áp dụng metadata mà nó nhận được. Cách resolve khác nhau giữa hai chế độ request. Full visit resolve toàn bộ tập prop đủ điều kiện. Partial reload chỉ resolve những prop client yêu cầu, dựa trên page component. Full visit Partial reload Một số field metadata chỉ áp dụng cho từng chế độ cụ thể:
  • deferredProps chỉ được điền trong full visit. Nó rỗng hoặc không tồn tại ở partial reload vì deferred prop được resolve trong request tiếp theo.
  • rescuedProps chỉ được điền trong partial reload, liệt kê các deferred prop không resolve thành công.
  • Metadata merge, scroll và once được phát theo từng response, cùng với những prop mang các hành vi đó.

Always props

Always prop được resolve trong mọi response ở cả hai chế độ. Chúng hoàn toàn bỏ qua filter partial reload, vì vậy một always prop vẫn được gửi kể cả khi request liệt kê nó trong except. Chúng không mang page-object metadata vì đây thuần túy là quy tắc resolve phía server. Prop errors là một always prop, đó là lý do mọi page object đều có object errors.

Kết hợp các nhóm

Một prop có thể đồng thời thuộc nhiều nhóm. Prop có thể vừa deferred vừa mergeable, vừa once vừa deferred, hoặc vừa scroll vừa deferred. Các field metadata độc lập với nhau, vì vậy page object mang mọi nhãn áp dụng, tùy theo chế độ, partial filter và các quy tắc reset ở trên.

Tải lại một phần

Tùy chọn partial reload cho phép bạn yêu cầu một tập con của props (dữ liệu) từ server trong các lần truy cập tiếp theo tới cùng page component. Đây có thể là tối ưu hiệu năng hữu ích nếu chấp nhận một phần dữ liệu trang có thể bị cũ. Xem tài liệu partial reloads để biết chi tiết. Request partial reload chứa header X-Inertia-Partial-Component và có thể kèm các header X-Inertia-Partial-Data và/hoặc X-Inertia-Partial-Except. Header X-Inertia-Partial-Data là danh sách phân tách bằng dấu phẩy các key props (dữ liệu) cần được trả về. Header X-Inertia-Partial-Except là danh sách phân tách bằng dấu phẩy các key props (dữ liệu) không nên được trả về. Nếu chỉ gửi X-Inertia-Partial-Except, server gửi mọi prop trừ các prop được liệt kê. Có thể gửi cả hai header cùng lúc; khi đó danh sách X-Inertia-Partial-Data thu hẹp response trước, rồi danh sách X-Inertia-Partial-Except được loại khỏi kết quả, vì vậy prop xuất hiện trong cả hai sẽ bị loại. Header X-Inertia-Partial-Component chứa tên component đang được partial reload. Điều này là bắt buộc vì partial reload chỉ hoạt động với request tới cùng page component. Nếu đích cuối cùng thay đổi vì lý do nào đó (ví dụ người dùng đã đăng xuất và giờ ở trang đăng nhập), partial reload sẽ không diễn ra.

Reset props

Header X-Inertia-Reset liệt kê các path prop mà client muốn reset trước khi áp dụng dữ liệu mới. Prop bị reset sẽ được resolve lại và trả về không có nhãn, có mặt trong props nhưng vắng khỏi mọi mảng merge, vì vậy client thay thế giá trị thay vì gộp vào nó. Client gửi reset path trong cả header X-Inertia-Reset và danh sách only. Với scroll prop, server còn đặt scrollProps[path].reset trong metadata; component infinite scroll dùng giá trị này để đồng bộ lại trạng thái phân trang với trang được trả về. Xem resetting props để biết API phía client.

Deferred và optional props

Deferred prop cho phép server công bố dữ liệu sẽ được tải trong request tiếp theo. Trong full visit, prop bị bỏ qua và key được liệt kê trong deferredProps, theo nhóm request mà nó thuộc về. Client gửi một partial reload cho mỗi nhóm để lấy dữ liệu; tên nhóm có thể tùy ý. Xem tài liệu deferred props.
Optional prop hoạt động tương tự nhưng không bao giờ được công bố. Chúng bị bỏ qua ở full visit và chỉ resolve khi partial reload chọn chúng qua only hoặc except.

Deferred props được rescue

Một deferred prop được resolve với rescue: true mà ném exception sẽ không làm response thất bại; response vẫn là 200 và chứa mọi prop khác. Server báo exception qua cơ chế xử lý lỗi của framework, loại hoàn toàn prop khỏi props (không gửi dưới dạng null) và thêm key của nó vào mảng top-level rescuedProps. Client dùng danh sách này để render slot rescue trên component <Deferred>. Xem xử lý lỗi.

Gộp props

Merge prop yêu cầu client kết hợp dữ liệu prop mới với dữ liệu đã có trên trang thay vì thay thế. Mảng được append hoặc prepend, còn object được shallow merge hoặc deep merge. Page object đánh dấu mỗi prop cần gộp trong mergeProps (append), prependProps (prepend) hoặc deepMergeProps (deep merge). Việc gộp chỉ áp dụng cho partial reload, vì vậy full visit luôn thay thế prop kể cả khi prop mang nhãn merge. Xem tài liệu merging props.

Khớp phần tử

Mảng matchPropsOn cho client biết field nào định danh từng phần tử để entry hiện có có thể được cập nhật tại chỗ thay vì bị nhân bản. Mỗi entry có dạng "<propPath>.<keyField>" và được tách tại dấu chấm cuối cùng: phần trước segment cuối là prop path, segment cuối là key field. conversations.data.id định danh mảng tại conversations.data theo field id. Xem matching items.

Once props

Once prop được resolve một lần và client ghi nhớ, sau đó tái sử dụng ở các trang tiếp theo có cùng prop. Page object mang cấu hình onceProps. Mỗi entry ánh xạ một key tới tên prop và timestamp hết hạn tùy chọn tính bằng millisecond. Xem tài liệu once props.
Trong các request Inertia tiếp theo, client gửi các once key đã tải và chưa hết hạn trong header X-Inertia-Except-Once-Props. Server bỏ qua việc resolve các prop đó và không đưa chúng vào response; client tái sử dụng giá trị đã tải trước đó.
Lưu ý plans có trong onceProps nhưng không có trong props vì nó đã được tải ở client. Key onceProps định danh once prop xuyên trang, còn prop chỉ định tên prop thực tế. Hai giá trị này có thể khác nhau khi dùng custom key.

Force-fresh và partial reload

Server có thể gửi giá trị mới cho once prop kể cả khi key của nó xuất hiện trong X-Inertia-Except-Once-Props, ví dụ khi dữ liệu nền đã thay đổi. Giá trị trả về cùng expiresAt mới sẽ thay thế bản sao ở client. Trong partial reload, header except-once bị bỏ qua, vì vậy once prop được yêu cầu luôn được resolve.

Infinite scroll

Infinite scroll xây dựng trên merge prop. Mảng bên trong của prop được đánh dấu để gộp (thường là <path>.data), còn page object mang entry scrollProps mô tả cursor của paginator. Xem tài liệu infinite scroll.
Mỗi scroll response đều phát lại nhãn merge và một cursor mới. Request reset còn đặt scrollProps[path].reset thành true, báo cho client đồng bộ lại trạng thái phân trang theo page được trả về. Deferred scroll prop không phát scrollProps trong full visit vì nó được resolve ở request tiếp theo.

Quản lý phiên bản asset

Page object mang định danh version đại diện cho phiên bản asset hiện tại của site. Giá trị có thể là số, chuỗi hoặc file hash, miễn là thay đổi khi asset thay đổi; server không theo dõi asset version nên gửi chuỗi rỗng. Client gửi lại version của page đang hoạt động trong header X-Inertia-Version, còn server so sánh hai giá trị, thường ở lớp middleware. Nếu version khớp, request tiếp tục bình thường. Nếu không khớp trên request GET, server lập tức trả 409 Conflict với URL đích trong header X-Inertia-Location và version hiện tại trong X-Inertia-Version, giúp client đến đúng đích kể cả sau server-side redirect. Request không phải GET không bao giờ nhận 409 do version mismatch, dù request GET sau redirect vẫn có thể nhận. Server-side adapter cũng reflash mọi flash session data trên 409 để dữ liệu tồn tại qua request tiếp theo.
Xem trang asset versioning để biết cách cấu hình version và cách background request được xử lý.

Redirect

Inertia dựa vào HTTP redirect tiêu chuẩn để điều hướng sau một thao tác phía server. 302 Found được trả về sau request PUT, PATCH hoặc DELETE sẽ được chuyển thành 303 See Other để trình duyệt gửi GET tới redirect target, tránh lặp lại request không phải GET. External redirect trỏ ra ngoài ứng dụng Inertia, nơi các request header của Inertia không thể đi theo, vì vậy XHR visit có thể không follow được. Thay vào đó server trả 409 Conflict cùng header X-Inertia-Location, và client thực hiện full visit bằng window.location. Redirect không phải prefetch có target chứa URL fragment được trả về dưới dạng 409 Conflict với header X-Inertia-Redirect chứa URL đầy đủ, sau đó client thực hiện Inertia GET visit mới tới URL đó. Cơ chế này khác field preserveFragment của page object, vốn mang fragment của request ban đầu qua redirect thông thường. Xem tài liệu redirects.

Lỗi validation

Validation error được chia sẻ qua prop errors. Laravel adapter đăng ký errors là always prop nên nó có mặt trong mọi page object và mặc định là {} khi không có lỗi. Mỗi key có thể ánh xạ tới một message hoặc một mảng message, và client render đúng shape nhận được. Việc chọn shape thuộc về server; vì vậy Laravel adapter mặc định gửi lỗi đầu tiên của mỗi field và có thể được cấu hình để gửi toàn bộ error message cho từng field. Request có thể scope error vào một error bag có tên bằng header X-Inertia-Error-Bag. Server namespace các error được trả về dưới bag đó, nhờ vậy nhiều form trên cùng trang có thể giữ lỗi riêng biệt. Xem tài liệu validation.

HTTP status code

Inertia sử dụng các HTTP status code cụ thể để xử lý những tình huống khác nhau. Các status code sau được dùng cho request validation bằng Precognition.

Server-side rendering

Mặc định Inertia không server-side render page component. Khi bật SSR, một wire contract thứ hai được đưa vào, lần này giữa server-side adapter và Node SSR server của Inertia. Adapter POST page object tới SSR server; server này trả markup đã pre-render cho tài liệu HTML.
Response điền vào hai slot của root template, được Laravel adapter cung cấp dưới dạng Blade component <x-inertia::head><x-inertia::app>. Mảng head chứa các phần tử thuộc <head> của tài liệu, chẳng hạn title và meta tag. Chuỗi body thay thế page object script tag và root <div> mà tài liệu không SSR sẽ render, vì SSR server đã đưa cả hai vào markup; nó còn mang data-server-rendered="true" để client hydrate DOM hiện có thay vì mount ứng dụng mới. Việc escape dấu gạch chéo trong page object nhúng do SSR server xử lý, nên adapter có thể in markup body nguyên trạng. SSR server cung cấp thêm hai endpoint. Request GET tới /health trả {"status":"OK"} và có thể dùng để xác minh process đang chạy trước khi gửi render. Request POST tới /shutdown dừng process; đây là cách command inertia:stop-ssr của Laravel adapter hoạt động. Render thất bại trả response 500 với JSON body phân loại lỗi thay vì chỉ báo lỗi chung.
Message error, hinttimestamp luôn có mặt, còn component, url, stacksourceLocation xuất hiện khi SSR server có thể xác định. type thu hẹp nguyên nhân thành browser-api nếu một browser global bị truy cập trong lúc render, đồng thời đặt browserApi thành API gây lỗi; component-resolution nếu không resolve được page component; hoặc render với các exception khác do component ném ra. Adapter nên xem render thất bại là lỗi không fatal: báo payload qua error handling của ứng dụng rồi fallback về tài liệu client-side rendered tiêu chuẩn, để SSR build lỗi không làm site ngừng hoạt động. Laravel adapter phát lỗi này thành SsrRenderFailed event và bổ sung type connection riêng khi hoàn toàn không kết nối được tới SSR server.

Tài liệu chính thức

Bài dịch này được đối chiếu từ tài liệu Inertia.js v3 chính thức. Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.