Replies: 3 comments 1 reply
-
Hey @mohsen1. I don't remember what the context was, but I prototyped basically exactly what you described a couple months ago: The Gist provides a runtime module used both on the client and server: import Static from 'server-only';
export default (pageProps) => (
<Static>
<ComponentThatRequiresData data={pageProps.data} />
</Static>
) It uses the The included Babel plugin can be used to completely remove the contents of A final step for Next would be marking the export function getServerSideProps() {
// fetch data and whatnot
const props = { ... };
// this could be automated based on the prop keys used within `<Static>..</Static>`
const toHide = ['data'];
for (const property of toHide) {
Object.defineProperty(props, property, { value: props[property] });
}
return props;
} The main issue I have run into when exploring this approach is that it doesn't really account for client-side navigation. When navigating on the client, you really need the original (un-removed) component definition and probably the data from |
Beta Was this translation helpful? Give feedback.
-
Thank @developit! that prototype looks promising! Eliminating the entire subtree has that pitfall as you mentioned. Something like a tab view will break down pretty quickly: function TabbedApp() {
const [tab, changeTab] = useState(0);
return <div>
<nav>
<button onClick={() => changeTab(0)}>Tab 1</button>
<button onClick={() => changeTab(1)}>Tab 2</button>
</nav>
{tab === 0 && <div><Static>Contents of Tab 1</Static></div>}
{tab === 1 && <div><Static>Contents of Tab 2</Static></div>}
</div>
} Because I wonder if there is a way to mitigate this issue? |
Beta Was this translation helpful? Give feedback.
-
The way we do static subtree is similar to `next/dynamic API. import static from './staticSubtree'
const Component = static(() => import('./component'), {
id: 'component',
// optional
fallback: null,
})
function StaticComponent(props) {
return <Component {...props} />
} Here we require 2 things: loader function (async import to the component), and the DOM node ID. The reason we need loader function, is because we want to be able to do client-side navigation. Having reference to the import allow us to use it on client-side navigation. The DOM id itself is used to fake the render/hydration. const rootSubtree = document.getElementById(id);
const isHydration = rootSubtree.innerHTML !== ''
if (isHydration) {
return <div id={id} dangerouslySetInnerHTML={{ __html: rootSubtree.innerHTML }} />
}
const { Component } = this.state
if (!Component) {
return fallback
}
return <Component {...props} /> We only call the loader function in async componentDidMount() {
if (!isHydration) {
const mod = await loaderFunction();
const Component = 'default' in mod ? mod.default : mod;
this.setState({ Component });
}
} In our There are 2 drawbacks with this approach:
Regarding |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This is something I've been interested for a while now. Currently Server Side Rendering involves sending data used to render components in server to the client for "rehydration". We also send down the same HTML in JS (JSX) but that's a different problem. In many cases that data is not actually being used because the rendered HTML is sufficient.
We can improve this by introducing "static boundaries" in pages so anything in between those boundaries would not repeat the server generated data in client's massive
window.__DATA__
JSON payload.How this can work?
This is probably going to be specific each framework but in general we want a sort of component that specifies those static boundaries:
How is it different than
getStaticProps
?getStaticProps
is great for build time only data fetching. What I'm proposing is improving howgetServerSideProps
sends data down to the client to re-use it for hydration.is this doable?
I don't know. I have to try this with Apollo but I thought I share my idea to get some feedback before spending a day or two trying to make this work? With Apollo I'm imagining marking the DOM with some sort of data attribute and then using the same DOM content to render the component that was using data in the server using
dangerouslySetInnerHTML
.Beta Was this translation helpful? Give feedback.
All reactions