Skip to content
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

fix: safari does not paint the fallback component #506

Closed
wants to merge 1 commit into from

Conversation

hkhere
Copy link

@hkhere hkhere commented Jan 9, 2020

While a async chunk is being loaded, safari will not paint the fallback component's dom untill the async chunk is completely loaded.

@gregberge
Copy link
Owner

Sorry the code is not correct, could you please add an issue instead to describe your problem.

@hkhere
Copy link
Author

hkhere commented Jan 10, 2020

@gregberge issue 509

@theKashey
Copy link
Collaborator

Any ideas why your code fixes the problem? Single setTimeout, double setTimeout... why?

@hkhere
Copy link
Author

hkhere commented Jan 11, 2020

@theKashey The intention is to put the requests of async chunks to other event loop phase, let safari paints the dom of the fallback component first.

It seems safari tries to do some optimizations by delaying the painting of dom if it is requesting some async chunks. But I did not really examine the source code of webkit.

I expected one setTimeout would do the job but it did not . So I tried double setTimeout and it does show the fallback component. Maybe we should/could find an more elegant solution.

@theKashey
Copy link
Collaborator

I've played with your example a bit, removed all possible side effects like hot-loader, even tried different code-splitting libraries, including React.lazy - everyone is affected.

Strangely why you were the first one who discovered this bug.

Wrapping initial load with timeout is more or less enough, however, there is no need to wrap suspense-related code (and you've broke something with it).

So - to resolve the problem it is enough to delay css loading via setTimeout(fn,1), and it's better to implement inside "loadAsync" method, not around it. Unfortunately my favourite "double promise" did not work at all.

Plus - such logic would make loadable a bit more stable. For example, right now it could be resolved almost synchroniously if scripts are cached using ServiceWorkers, which might lead to some unpredictable errors.

@theKashey theKashey reopened this Jan 11, 2020
@theKashey
Copy link
Collaborator

theKashey commented Jan 11, 2020

It's also enough to call document.body.offsetLeft (cause reflow) to solve the issue.

It's also as well enough to change extract-mini-css-plugin to inject styles into body instead of head, and it would resolve the issue.

Let's first find a bug in webkit bug tracker.

@theKashey
Copy link
Collaborator

Ok. I am closing this PR.
Adding any timeouts of another sort of hacks there does not solve the problem:

Yes - you will see "Loading", not NO, just after it a __whole application would be frozen until css file is loaded".

I make a simple example, based of your code:

const Home = lazy(() => new Promise(resolve => setTimeout(() => resolve(import('./Home')), 1000)));
// ^^ delay import my 1s to let "loading" be displayed

const App = () => {
  const [state, setState] = useState(0);
  useEffect(
    () => {
      setInterval(() => setState(s => s + 1), 100);
    },
    []
  );
  return <div>
    <React.Suspense fallback={<Loading/>}><Home/></React.Suspense>
    {state}
     here is a counter, changing 10 times per second... 
  </div>
}

export default App;

Long story short - counted would not count.

This problem should be solved elsewhere.

@hkhere
Copy link
Author

hkhere commented Jan 11, 2020

Adding any timeouts of another sort of hacks there does not solve the problem

This problem should be solved elsewhere.

@theKashey Totally agree. I should have just opened an issue instead of an pr with terrible code.

@hkhere hkhere deleted the safari-lazy-painting branch January 11, 2020 04:48
@theKashey
Copy link
Collaborator

@hkhere - you did everything right. You raised the issue, then raised attention to the problem, you led to the underlying problem discovery, and, as a result, you will get your issue fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants