Skip to content

Data fetching with SSR #38

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

Closed
scottbedard opened this issue May 30, 2019 · 2 comments
Closed

Data fetching with SSR #38

scottbedard opened this issue May 30, 2019 · 2 comments

Comments

@scottbedard
Copy link
Contributor

What is the best way to fetch data that is part of a route? For example, imagine a /blog/:slug route. Ideally, SSR would produce the full page, including the blog content, so that upon hydration no additional XHRs are necessary.

I found this issue that looks like it might solve my problem, but it looks sort of old, so I'm not sure if there is a better way to achieve what I'm talking about.

Any advice here would be appreciated, thanks!

@EmilTholin
Copy link
Owner

EmilTholin commented May 31, 2019

Hi @scottbedard!

It might be that an asynchronous streaming renderer makes this easier in the future, but for now I think you are best off using some React/Redux-like SSR setup.

You get the data on the server and render the topmost Svelte component with the data. You then render this same data as a global variable for the topmost front end JavaScript file to read and give to the topmost Svelte component in the browser as well. You could then e.g. supply this data to the entire app through context in the topmost component.

Example

// server.js
const app = require("./public/App.js");

const server = express();

server.use(express.static(path.join(__dirname, "public")));

server.get("*", async (req, res) => {
  const preloadedState = await getStateForUrl(req.url);
  preloadedState.url = req.url;
  const { html } = app.render(preloadedState);

  res.write(`
    <!DOCTYPE html>
    <div id="app">${html}</div>
    <script>
      window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(
        /</g,
        '\\u003c'
      )};
    </script>
    <script src="/public/bundle.js"></script>
  `);

  res.end();
});
<!-- App.svelte -->
<script>
  import { setContext } from "svelte";
  import { writable } from "svelte/store";
  import { Router } from "svelte-routing";

  export let url;
  export let foo;
  export let bar;

  const appStore = writable({ foo, bar });

  setContext('appStore', appStore);
</script>

<Router {url}>
  <!-- ... -->
</Router>
// main.js
import App from "./App.svelte";

new App({
  target: document.getElementById("app"),
  hydrate: true,
  props: window.__PRELOADED_STATE__
});

I think it should be fairly straight-forward to modify the example in this repository with this functionality.

@scottbedard
Copy link
Contributor Author

Dang, that's sort of what I thought. This will work, but it means any page that requires initial state needs to to two things instead of one to get that state.

  1. Check if it's in the initial state
  2. If not, fetch it from the server

Maybe in the future this will be possible, but until then I guess it's not the end of the world. Thanks for the info!

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

No branches or pull requests

2 participants