-
Notifications
You must be signed in to change notification settings - Fork 468
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing SSR in large commercial project. #683
Comments
Hey @Tarvald, I hear ya, but this probably isn't the right place to ask whether you should stop using redux-observable 😆 SSR is possible today with redux-observable, but indeed depending on exactly what SSR means for your use case, you have to provide some custom code yourself. That caveat has been one of the big reasons we've never shipped anything: I've seen several different opinions on how it should work, and in some cases they conflict and are incompatible with each other. e.g. whether you want to wait for epics to shut down gracefully, or force them to shutdown. Whether we'll ever provide helpers around this is not clear, but there will likely be improvements to some things that will make it easier e.g. ability to have state$ complete(), which isn't possible today without rolling your own state$ Observable that you wrap ours with and provide to your root epic. There's no time frame on this though, unfortunately. I'm not currently doing SSR myself--but if anyone reading this knows what to do, they're welcome to PR if they want to get something in more quickly. Ultimately though, remember it is is still possible even without any changes in redux-observable_. It just isn't as easy as it could be. Wish you and your team the best. 👍 |
@jayphelps I have been reading all the PR (539 and 412) and the discussions and am very interested into this topic as well. My use-case is very easy but I haven't gotten SSI to work without modifying redux-observable itself as the PR requests suggest. Since you say it is is still possible even without any changes in redux-observable, could you point me to a working example or into the right direction? That would be awesome |
@japrescott, @Tarvald Look at this comment under #539 with a stackblitz example. This pattern should provide a basic way to use redux-observable with SSR. |
@aplassen Thank you for your reply! I have been looking at the stackblitz implementation from jayphelps and have tried to adapt it into my project. But as far as far I can see, it provides only the possibility to stop further actions from being waited for and then resolves the promise after the already dispatched actions are "complete". Maybe my usecase is not as simple as I assume, but my flow of action is 'get_data' -> rxjs.ajax -> 'data_done'. And I expect to know when 'data_done' has been called.
|
@japrescott , so if I understand it correctly, you have another epic that is listening for the action "actions.fetchData.done"? |
Hi Guys However It is only works one time. |
@Tarvald, on the second render-pass, no epics should be listening. For this method to work, whatever the epics need to do, they need to do it before the second render-pass. In the example |
@aplassen I think this problem is related to our application structure, we are creating store in runtime so its not reinit on call to server. However I am not sure if I should recreate store from scratch each time even if every user need init store it does not mean he / she needs brand new store object. So It would be great to reset above approach on demand :) But so far so good! |
@aplassen thank you for your reply. I noticed that in my setup the shutdown$ subject was declared outside my store which caused it to resolve early. Everything works now. thank you very much! @Tarvald you will need to dispatch your actions manually for each route and cant rely on useEffect hook |
@japrescott |
@japrescott, cool that you got it to work 👍 @Tarvald
Be wary of memory leaks and "data leaks" between requests. It is important that each request get their own independent copy. What you can do is this:
|
Also, to address the concerns that @jayphelps had relating to the risk of epics not actually completing, leaving the request "hanging":
One could wrap the epics that are expected to run on the server with a const myUniversalEpic = universalEpic(($action) => (
$action
.pipe(
ofType('PING'),
switchMap(() => (
of({ type: 'PONG' })
.pipe(
delay(120 * 1000), // running way too long
)
)),
)
)); What import { ofType } from 'redux-observable';
import { of } from 'rxjs';
import { delay, takeUntil, tap, catchError } from 'rxjs/operators';
const UNIVERSAL_EPIC_TIMEOUT = 10 * 1000;
function universalEpic(epic) {
function _epic(action$, ...args) {
return epic(action$, ...args)
.pipe(
catchError((error) => (
of({ type: 'APP_EPIC_UNCAUGHT_ERROR', error })
)),
takeUntil(
action$
.pipe(
ofType('APP_SHUTDOWN_IN_PROGRESS'),
delay(UNIVERSAL_EPIC_TIMEOUT),
map(() => ({ type: 'APP_SHUTDOWN_IN_PROGRESS_END' })),
tap(() => {
console.error(`SSR: Epic "${epic.name || '<anonymous>'}" timed out, pulling the plug!`);
}),
),
),
);
}
// Enable us to only include universal epics on serverSide
_epic.isUniversalEpic = true;
return _epic;
}
export default universalEpic; |
Hi Again! export function configureStore() {
} It was working flawlessly since we had to implement the last route to be fully rendered on the server. (seriously!) On the server, we are doing two renders, by launching renderToString method twice. But we have one case where async action can reveal another constructor with extra async action that does not count during the first render. Do you know how to deal with it? Best regards |
Hi guys,
We have quite large commerce app. We need to implement SSR however our whole communication is going through redux-observable.
Previous developer recommend to rewrite all epics to redux-saga. We have them more then 50.
What do you think, should we do this migration or we maybe we should develop own solution based on this PR?
Or maybe this solution would be still working?
I also found react-redux-epic library.
Guy here said 18 days ago that he is still using it and its working.
Our epics are in most cases are very simple. Mostly we do some ajax calls and fill store with data.
Sometimes we do some transformations or we dispatch other actions, but in general they are pretty straightforward.
All we need to do on server is to dispatch few actions (the same we have in componentDidMount) and wait for other few actions to be dispatched (success actions).
Maybe you know how to listen on action$ in server function?
What do you think we should start migration of 50 (or even more) epics to redux-saga or we should spend few days on getting working redux-observable event if ssr is not nativly supported?
I am using redux-observable for few years now but I don't feel strong enough to make decision at least now.
Btw redux-saga based on promise but I always though that streams are just more advanced promises. :)
Have a good day and thanks for any response :)
The text was updated successfully, but these errors were encountered: