feat(v2): add a way to exclude components from build-time prerendering - #2323
Conversation
|
Deploy preview for docusaurus-2 ready! Built with commit 63ee326 |
| import React, {useEffect, useState} from 'react'; | ||
|
|
||
| const ClientOnly = ({children}) => { | ||
| const [isClient, setIsClient] = useState(false); |
There was a problem hiding this comment.
I think isComponentMounted will be a better name.
| import React, {useEffect, useState} from 'react'; | ||
|
|
||
| const BrowserOnly = ({children}) => { | ||
| const [isClient, setIsClient] = useState(false); |
There was a problem hiding this comment.
Btw I'm wondering if we can use the ExecutionEnvironment.canUseDOM instead, then there's no need for a state right?
There was a problem hiding this comment.
Why so? This state is needed.
There was a problem hiding this comment.
What's the diff between doing your way and this:
function BrowserOnly({children}) => {
return ExecutionEnvironment.canUseDOM && children;
}There was a problem hiding this comment.
It seemed to me that all the work of this component is to use useEffect, isn't it?
There was a problem hiding this comment.
Yes and I think we don't even need useEffect here. Can you try what I've proposed and see whether there's any difference? :/
There was a problem hiding this comment.
It seems that none of the options actually works, it really puzzled me and in complete dismay 🤒
P.S. For the test, I used the @u-wave/react-vimeo component in the MDX file.
There was a problem hiding this comment.
So even your current implementation doesn't work? Luckily we test out first lol. Maybe the component is running some side effects that relies on browser environments being present during import. In that case there's no way around it.
There was a problem hiding this comment.
Not exactly, rather why something does not work, this component on some dependencies.
There was a problem hiding this comment.
After some investigation I found out that build fails if a component using a window object is imported, how is this possible? Therefore the BrowserOnly component is useless here 🤷♂️
There was a problem hiding this comment.
I went to test this component out and it doesn't seem to work. I'm not sure why but I think we can't let the children be JSX, we have to let it be a render function.
To reproduce the bug, add
<BrowserOnly>{window.location.pathname}</BrowserOnly>to any page and try to build it. It will fail.
But if you do this:
<BrowserOnly>{() => window.location.pathname}</BrowserOnly>along with the suggested change of doing children() within BrowserOnly.js, it will be fine.
Will need to change the docs also and say the contents have to be a render function. Will also be good to have tests.
|
|
||
| import React, {useEffect, useState} from 'react'; | ||
|
|
||
| const BrowserOnly = ({children}) => { |
There was a problem hiding this comment.
This also works and is shorter IMO.
function BrowserOnly({children}) {
return ExecutionEnvironment.canUseDOM && children != null && <>{children()}</>;
};Let's use function declaration for functional components.
There was a problem hiding this comment.
Thanks, although this does not solve the issue of importing components using window.
For example, if I just import this component in the MDX file, then I will have an error during the building that the window is not defined.
import {Replay} from 'vimond-replay';There was a problem hiding this comment.
In that case, users will have to lazy load the component after the component has mounted. There's no way we can handle that with the suggested component here.
|
@lex111 shall we try to get this into the next release? |
|
@yangshun done ✔️ |
yangshun
left a comment
There was a problem hiding this comment.
I will fix this if you don't get to it by tonight so that we can include this in the next release.
| import BrowserOnly from '@docusaurus/BrowserOnly'; | ||
|
|
||
| <BrowserOnly> | ||
| {/* Something that should be excluded during build process prerendering. */} |
There was a problem hiding this comment.
We need to give an example to show that children should be a render function and not normal children.
facebook#2323) * feat(v2): add a way to exclude components from SSR within JSX * Update docusaurus-core.md * Update and rename ClientOnly.js to BrowserOnly.js * improve docs * Improve naming * Simplify realization * Fix code style * Fix docs * Update docusaurus-core.md Co-authored-by: Yangshun Tay <tay.yang.shun@gmail.com>
Motivation
Resolve #2273.
Have you read the Contributing Guidelines on pull requests?
Yes
Test Plan
ClientOnlyput component that usedwindowobject, eg.Related PRs
(If this PR adds or changes functionality, please take some time to update the docs at https://github.com/facebook/docusaurus, and link to your PR here.)