Client-Side and Server-Side Workflow
Client-Side and Server-Side Workflow
Client-Side and Server-Side Workflow
A major point of distinction in the architecture of any web application front-end is whether its interaction with a given service, the BigCommerce GraphQL Storefront API in our context, occurs in a client or server context. Client-side requests are performed directly in a user’s browser, while server-side requests involve a server layer that retrieves data from the API before page content is ever served to the client.
The choice of data fetching strategy is often intrinsically connected to rendering strategy. In web applications with a heavily client-side approach, data fetched within the browser is then used to hydrate page content using JavaScript-based techniques. With a server-side strategy, the API-fetched data is directly incorporated into the rendered page content initially sent to the user’s web browser.
Client-side rendering is often beneficial for highly dynamic and interactive user interfaces. A web application that exclusively fetches and renders content in the browser can often be deployed as static content on a CDN, without the need for traditional server resources like databases, cache storage, or script runtimes. Since purely client-rendered applications do not have to make repeated round trips to the web server for re-rendering as content on the page changes, they can potentially present an experience that feels quicker and more responsive. Progressive Web Applications are web-based apps that look and feel like native apps, can be installed on a user’s device, and often have limited offline capability. These apps usually benefit from client-side data fetching and rendering.
For traditional websites, there are a number of hurdles that client-side fetching and rendering strategy must overcome. JavaScript-based applications must implement solutions for URL-based routing and intuitive integration between page content and browser history. Search engine optimization is more challenging since content is not present in the initial HTML sent in the page response (although search engine support for JavaScript-generated content continues to become more reliable). Most importantly, client-side data fetching means that API endpoints and authentication credentials — a GraphQL token in our case — are publicly exposed. As a result, such tokens should be short-lived and regenerated frequently.
Server-side rendering is the way content has been delivered since dynamic websites first emerged. Pre-rendered pages are compatible with standard web navigation flow without any extra effort, and they lend themselves to more reliable search engine optimization. Server rendering allows data fetching to be done on the server as well, which means that API endpoints and auth tokens remain private. Applications benefit from a server-side strategy when they present and navigate like traditional websites or when it’s necessary to fetch data in a private context. Modern frameworks like Next.js and Nuxt incorporate the benefits of front-end toolsets (React and Vue) while adding support for server-side rendering, combining secure data fetching and fully rendered page responses with client-side routing and dynamic interaction. This means that modern web applications can often embrace server-side data fetching without sacrificing responsive user interfaces.
Most ecommerce storefronts navigate like traditional websites, require reliable search engine optimization, and benefit from the simplicity of private data fetching. As such, a server-side strategy for data fetching and rendering is an increasingly common choice. Which strategy works best for you will ultimately depend on the unique goals and requirements of your own application. Hybrid approaches are perfectly valid as well. For example, critical content like the main product details on a product page might be rendered on the server, while the product’s reviews are less essential and can be loaded with a client-side fetch (using a different GraphQL token) after the initial page is rendered.
Whatever strategy you choose, note that the distinction between client-side and server-side data fetching has no bearing on whether a front-end is compatible with composable architecture. A headless storefront is defined by its decoupled relationship with the services it consumes, not by whether the interactions with those services occur in a browser or in a server layer.
A Storefront API token — generated with the /v3/storefront/api-token REST endpoint — is designed for client-side use only. It supports a couple of strategies that facilitate secure access and user context in a browser environment.
The Storefront API token was previously supported in server-side contexts. This is no longer the case — it is now client-side only.
allowed_cors_origins parameter of the Create Token request allows you to specify the domains that CORS (cross-origin resource sharing) rules will allow for requests using the resulting token. For example, let’s say a token is created with an allowed origin of petespastries.com. When a page served from that domain executes a JavaScript-initiated request to store-{hash}.mybigcommerce.com with that token, BigCommerce will recognize the referring domain and return data. If a malicious actor obtains this token and entices users to execute a similar request from a page on pastryfraud.com, the request will be rejected.SHOP_SESSION_TOKEN cookie. This cookie, as it does in a typical Stencil storefront, tracks the user’s session context. When the session cookie is sent along with future requests, this automatically provides the right customer context. For example, if a Customer Login mutation is performed from a user’s browser, any future requests from that user for catalog data will receive accurate customer pricing thanks to the customer context provided by the session cookie.A number of challenges make relying on the SHOP_SESSION_TOKEN cookie a less than ideal solution for tracking state across requests.
Prevalent privacy concerns with data sharing on the web have led to more restrictions on cross-domain cookies by browser vendors. This has implications for the session cookie if your storefront domain is not the same as your BigCommerce GraphQL domain.
Let’s say that petespastries.com is a headless storefront making client-side GraphQL requests to a BigCommerce endpoint on a different domain. (Perhaps Pete’s BigCommerce store has the domain pete-bc.com, or perhaps the storefront is simply sending requests to store-{hash}.mybigcommerce.com.) This constitutes a cross-domain cookie scenario.
With the right configuration for your client-side requests, cross-domain cookies can still be sent and can provide the right context for your queries. However, cross-domain cookie rules continue to change, and several browser vendors have signaled clear plans to restrict them further in the future.
Even if you can adopt a DNS strategy that puts the storefront on the same domain as the BigCommerce endpoint (say, in the above example, a domain like api.petespastries.com), it is still inadvisable to rely on a cookie created and controlled by the BigCommerce web service for session state important to your own front-end application.
It is recommended practice to disregard the SHOP_SESSION_TOKEN cookie and avoid relying on it for customer context in a headless storefront.
In cases where you are using a client-side fetching strategy and must maintain customer or cart context on such requests, we recommend proxying your requests via a server layer that can use a customer access token. We will discuss strategies for tracking the customer context when we dive into the topic of customer authentication.
A Private Token — generated with the /v3/storefront/api-token-private REST endpoint — is designed for headless server-to-server integrations. It is the recommended token type for headless storefronts and other server-to-server applications.
For more details on creating and using Private Tokens, see Creating a Private Token.
In a server-side context, a Private Token is used in conjunction with a Customer Access Token — generated with the login mutation or the loginWithCustomerLoginJwt mutation — to facilitate data fetching with customer context.
A customer impersonation token (CIT) — generated with the /v3/storefront/api-token-customer-impersonation REST endpoint — is an alternative method for providing customer context and is necessarily relegated to server-side data fetching.
X-Bc-Customer-Id header.Using a customer impersonation token in combination with a customer ID is an alternative way of providing customer context, in contrast with using a standard token with a customer access token. This is a legacy approach, and because of the elevated privileges of a CIT, the customer access token approach is the preferred method.