The unified invocation of BFF functions is isomorphic in both CSR and SSR. The request SDK encapsulated by Modern.js relies on the Fetch API on the browser side, and on node-fetch on the server side. However, in actual business scenarios, additional processing may be required for requests or responses, such as:
To address these scenarios, Modern.js provides the configure function, which offers a series of extension capabilities. You can use it to configure SSR passthrough request headers, add interceptors, or customize the request SDK.
The configure function needs to be called before all BFF requests are sent to ensure that the default request configuration is overridden.
import { configure } from '@modern-js/plugin-bff/client';
configure({
// ...
})
const Index = () => <div>Hello world</div>
export default Index;When using both Modern.js SSR and BFF, it is often necessary to pass some request header information from the SSR page request to the BFF service.
For example, imagine a project with a page URL https://website.com. This page is rendered using SSR, and in the component, it will call the API endpoint https://website.com/api/info, which requires the user's cookie information for authentication. The page needs to pass the cookie of the SSR page request to the BFF when requesting this API endpoint.
Currently, the following request headers are automatically passed through in Modern.js:
['cookie', 'user-agent', 'x-tt-logid', 'x-tt-stress']You can configure additional request headers using configure. For example, in the following snippet, Modern.js will automatically pass the x-uid information from the SSR page request to the BFF service:
configure({
allowedHeaders: ['x-uid']
})In some business scenarios, you may need to handle requests and responses uniformly. This can be achieved by configuring interceptors:
configure({
// The `request` here is the default request tool for unified invocation. The `interceptor` function needs to return a new request.
// The output of the new request must be the parsed body result.
interceptor(request) {
return async (url, params) => {
const res = await request(url, params);
return res.json();
};
}
});If configuring interceptors alone cannot meet your needs and you want to customize the request function, you can also configure it using configure:
import nodeFetch from 'node-fetch';
const customFetch = (input: RequestInfo | URL, init: RequestInit) => {
const curFetch = process.env.MODERN_TARGET !== 'node' ? fetch : nodeFetch as unknown as typeof fetch;
return curFetch(input, init).then(async res => {
const data = await res.json();
data.hello = 'hello custom sdk';
return data;
});
};
configure({
request: customFetch,
});There are some conventions when configuring custom request functions:
Below is an example of using axios to customize a request function:
import { configure } from '@modern-js/plugin-bff/client';
import type { Method, AxiosRequestHeaders as Headers } from 'axios';
configure({
async request(...config: Parameters<typeof fetch>) {
const [url, params] = config;
const res = await axios({
url: url as string, // Here we need to use `as` because fetch and axios types are somewhat incompatible
method: params?.method as Method,
data: params?.body,
headers: params?.headers as Headers,
});
return res.data;
},
});