Nanostores in SSR
Hi there!
I saw news on new release, saw allTasks API and decided to research, how nanostores is compatible with SSR
Loading of Node.js template in codesandbox takes forever for some reason, so i decided to create similiar reproduce with basic one:
https://codesandbox.io/s/loving-wilson-4vp4r?file=/src/index.js
(see index.js and console)
Idea is the same:
- Request happens
- Request-handler task is added to event-loop and starts some logic and web or db requests
- Once those web or db requests are over, state is recalculated with new data
- State injected in the app, which then rendered to string
- Resulting string sent as response
During all of these operations is important to isolate state that "belongs" to different requests from each other - otherwise data from one request will leak to the other
Nanostores have two issues there:
States of nanostores are shared between requests, which then leads to data prepared for one request to show in another - in result rendered html-string is not correct.
State of internal
allTaskscounter is also shared between all requests, which leads to weird bug: responses are not sent until all requests are handled, even if their data is ready.
Possible solutions:
- Many state-managers require creation of new instance of store/stores for every request, like this
const ssr = async (request) => {
const stores = initStores()
await stores.startLogic(request)
return renderAppToString(stores)
}This will effectively isolate requests from each other, because all of them will have their own instance of stores and all pending operations also will be bounded to this instance Mobx example: https://github.com/vercel/next.js/tree/master/examples/with-mobx-state-tree
- Some other state-managers, like
effector, allow to create separate instance of app state in special way, allowing to reuse already initialized stores and connections, like this:
const ssr = async (request) => {
// all stores and connections already defined somewhere
const scope = fork()
await allSettled(startLogic, { scope, params: request })
return renderAppToString(scope)
}Example: https://github.com/GTOsss/ssr-effector-next-example/blob/effector-react-form-ssr/src/pages/ssr.tsx
Source: nanostores/nanostores