Meteor-Community-Packages / meteor-fast-render

Render your app before the DDP connection even comes alive - magic?

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Why Subscribe to something that is not in the database

Saeeed-B opened this issue · comments

Why Subscribe to something that is not in the database

Hi, first of all, I'm very happy that fast render is back
But I have a problem with this package that was not resolved and caused me to stop using this package.
I have already stated the issue here:

abecks/meteor-fast-render#35
https://forums.meteor.com/t/why-subscribe-to-something-that-is-not-in-the-database/54492

Have you solved this problem?
Can your package be trusted?

I will definitely look into this.

Small update on this.. I've managed to narrow down where in the code this happens, but not why it happens.

For some strange reason when the data that is encoded into the html gets decoded, it doesn't decode properly. I can log out the result and see the wrong data. The strange part is that if I log out the string of data that needs to be decoded, into the console, and then pass that same string to the same decode function manually in the console, I get back the properly decoded data.. 🤦‍♂️

Right now I'm just trying to figure out what the hell the difference in the string contained in the variable, and the string after it's logged to the console.

I'm very happy to follow you, this gives us more hope for the meteor.
You should know that this is very important, because the reliability of the fast rendering package causes a big change in the meteor.
I will raise this issue again in the forum and I hope my friends can help

I'm not sure you'll find much help on this issue via the forums as it would require a pretty intimate knowledge of the internals of the package, and I'm not sure how many people would have that, or be willing to gain it. That being said, my promise to you is that this will be resolved, and I'm getting closer.

Thank you very much
Good luck

Small update on this.. I've managed to narrow down where in the code this happens, but not why it happens.

For some strange reason when the data that is encoded into the html gets decoded, it doesn't decode properly. I can log out the result and see the wrong data. The strange part is that if I log out the string of data that needs to be decoded, into the console, and then pass that same string to the same decode function manually in the console, I get back the properly decoded data.. 🤦‍♂️

Right now I'm just trying to figure out what the hell the difference in the string contained in the variable, and the string after it's logged to the console.

I am not sure if I can follow correctly and when you exactly log, but I would guess the following happens here:

  • the json-string in the html is correct and does not contain the duplicate. Easy to check (its just a urlencoded json string as far as i remember).
  • Once data "hydration" happens, it gets put into local mini mongo, which is currently empty
  • then, local subscription happens, it sends the subscribe ddp-calls, etc. and receives the added calls for this collection
  • It should now merge the documents, but i guess this is the moment where something wrong happens

console.log can sometimes be a bit missleading as it does not always show an object how it was when the log happend. If it is immediatly mutated (in the same tick), you see the updated object. A trick is to use console.log(JSON.stringify(obj, null, 2)) as it forces serialization of the object. (arg 2 is to indent the json string).

Maybe use that to narrow it down further!

After spending approximately 6 hours on this, it boils down to this. When either FastRender.onPageLoad or FastRender.onDataReady run, they call FastRender.wait to tell FastRender not to run its default data loading behavoir. This default behavior runs within a Meteor.startup so that onPageLoad or onDataReady get to run first and can call wait beforehand. If you run your UI code also from within a Meteor.startup then onPageLoad or onDataReady will be called after the default loading behavior and will cause the data be loaded twice which causes the strange artifacts that you are experiencing..

In your reproduction repo you're client UI code path starts here, and as you can see you are importing from within Meteor.startup. Importing from the top level of the file will fix your issue here.

I'm going to see if I can do some refactoring to make this load order unnecessary. If that's not possible, at the very least I'll make note of this possibility in the README, and have the code throw an error and display some information about why and how to fix it.

For now I'll consider this resolved.

@copleykj

First of all, thank you very much for your efforts
Secondly , Do you mean that the client code should not be inside Meteor.startup?

In your reproduction repo you're client UI code path starts here, and as you can see you are importing from within Meteor.startup. Importing from the top level of the file will fix your issue here.

You seem to have tagged my code incorrectly. Because you showed Meteor.startup on the server, not the client
But in the description you mentioned Meteor.startup in the client

Yes sorry. It should be client/main.jsx

Meteor.startup can be removed from the server code though as well, since there is no advantage to the delayed execution.

3a78e32 removes the possibility for this to happen so once V4 is released, this will be completely resolved.

I do not think the problem is solved.
I removed Meteor.Startup from client and server.
But the issue remains as follows:
No problem as long as the server renders and no extra data is shared.
But as soon as the client is rendered, additional data comes in the subscription.

Of course, it is very strange, sometimes this shape appears and sometimes the removal of m

@copleykj
My Server Code :

//-------------------- SSR -----------------------\\
    import React from "react";
	import { StaticRouter as Router } from "react-router-dom"
	// import { onPageLoad } from "meteor/server-render";
	import { FastRender } from 'meteor/communitypackages:fast-render'
    import { renderToString } from "react-dom/server"
    import { HelmetProvider } from 'react-helmet-async'
    import { LoadableCaptureProvider, preloadAllLoadables } from 'meteor/npdev:react-loadable'
	import Routes from "../../Routes/Routes";
	preloadAllLoadables().then(() => FastRender.onPageLoad(sink => {
		const context = {};
		const loadableHandle = {};
		const helmetContext = {};

		const html = renderToString(
			<LoadableCaptureProvider handle={loadableHandle}>
				<HelmetProvider context={helmetContext}>
					<Router location={sink.request.url} context={context}>
						<Routes />
					</Router>
				</HelmetProvider>
			</LoadableCaptureProvider>
		);

		const { helmet } = helmetContext;
		sink.appendToHead(helmet.meta.toString());
		sink.appendToHead(helmet.link.toString());
		sink.appendToHead(helmet.title.toString());

		sink.renderIntoElementById('App', html)
	}))

//------------------- End SSR ---------------------\\

My Client Code :

async function main () {
    const [
        React,
        ReactDOM ,
        { BrowserRouter },
        { HelmetProvider },
        { preloadLoadables },
        { default: Routes},
        { default: ScrollToTop},
        { FastRender }
    ] = await Promise.all([
      import('react'),
      import('react-dom'),
      import('react-router-dom'),
      import('react-helmet-async'),
      import('meteor/npdev:react-loadable'),
      import('../../Routes/Routes'),
      import('./ScrollToTop'),
	  import('meteor/communitypackages:fast-render')
    ]);
  
    const renderMethod = module.hot ? ReactDOM.render : ReactDOM.hydrate;
    const helmetContext = {}
    // const { default: Routes} = await import('../../Routes/Routes')
    FastRender.onPageLoad(async sink => {
        const promisables = preloadLoadables()
        await promisables
        ReactDOM.hydrate(
            <HelmetProvider context={helmetContext}>
                <BrowserRouter>
                    <ScrollToTop />
                    <Routes/>
                </BrowserRouter>
            </HelmetProvider>
        , document.getElementById('App'));
    })

}
main();

withOut Any Meteor.StartUp

If you go to the following address and check the minimongo with the Meteor extension, you will notice that there is a data that does not have id_, this is the extra data.
And this program is without Meteor.StartUp.

https://ghadr.org/