A co jeśli user ma wyłączony JS? A co jeśli userowi nie zadziała JS? A co jeśli nowa wersja Chrome'a ma mega buga, który de facto ubija funkcjonalność Ajaksa? A co jeśli proxy wytnie JS? A co jeśli komórka usera straci zasięg i nie doczyta JS-a?
Warto zauważyć, że chyba wszystkie duże i liczące się frameworki na rynku odkryły, że istnieje coś takiego jak "server side rendering". W tym segmencie przoduje od dawna Ember.js, ale React czy Angular 2 podobne techniki również wypracowały. Jak bardzo ważna jest to kwestia, świadczy fakt istnienia tak bardzo hackowatych usług jak chociażby Prerender.IO. I choć głównymi motywacjami twórców frameworków jest zdecydowanie wydajność czy lepsze dostosowanie pod SEO, tak naprawdę znacząco podnosi to dostępność danej strony. Kiedyś nazywano to "izomorficznym JS-em", obecnie to "uniwersalny JS".
I cały ten trend komponuje się także bardzo dobrze ze zmianami, jakie zachodzą po stronie backendu, gdzie coraz żywsza staje się idea middleendu (czy też – jakby to powiedział ktoś z 2016 roku – "backends for frontends"). Idea ta jest bardzo prosta: sam backend to nic innego jak REST API, które zwraca czyste dane (czy to jako JSON, czy to jako XML). Middleend z kolei to usługa, która pośredniczy między klientem (frontendem) a backendem. Usługa, która zwraca pobrane z backendu dane w formie, w której życzy sobie klient. Może to być np. zlepek odpowiedzi z kilku endpointów REST API, ale może to być też gotowy HTML (gdy np. wiadomo, że klientem jest super stary fon). Tak zaprojektowana architektura aplikacji pozwala dostarczać klientowi tego, czego mu potrzeba.
Oczywiście nie zachęcam w tym wypadku do takiej rozbudowy architektury, bo zapewne byłoby to z jednej strony niesamowicie pracochłonne, z drugiej zaś – stanowiłoby pewnie typową armatę na muchę. Niemniej uważam, że odpowiedź z serwera powinna być dostosowana do potrzeb klienta. Oznacza to ni mniej, ni więcej, że jeśli klient posyła żądanie Ajaksem, zwracamy mu czyste dane. W innym wypadku zwracamy mu gotowy HTML. Na takiej zasadzie działa chociażby (zapomniany już [*]) Taunus czy dziwaczny, przekombinowany, ale wciąż ciekawy Next (co pokazuje empirycznie, że React faktycznie się do takich rzeczy nadaje!). No i zawsze zostaje tradycyjny pjax, który również zachęca do takich działań w swoim README.
TL;DR Klient odpytuje serwer Ajaksem – JSON. Klient wysyła normalne żądanie – HTML.