简体   繁体   中英

Server side rendering + routing with Riot.js?

I'm using Node + Riot.js + Grapnel routing library (which can work on both client and server). I managed how to set up routing on the client but I can't figure the way to make it work on the server.

The current functionality of my client router is simple. I'm just sending opts.route to the proper component and then it mounts the requested page (which is also a component) to a div .

<x-layout>
  <div id="app-body"></div>

  <script>
    this.on('mount update', function() {
      riot.mount('#app-body', 'x-page-' + opts.route);
    });
  </script>
</x-layout>

But with riot.render(tag, {page: 'dashboard'}) it doesn't mounts the <x-page-dashboard> to #app-body .

When I remove this.on('mount update' ... wrapper it gives me an error

.../node_modules/riot/riot.js:1918
TypeError: (ctx || document).querySelectorAll is not a function`

which is obvious, because Node can't perform DOM manipulations.

I also tried to dynamically load components, like this

// Riot doesn't compiles such expressions `<x-page-{opts.route}>`
var tag = riot.tag2('x-layout', '<div id="app-body"><x-page-{opts.route}></x-page-{opts.route}></div>');
riot.render(tag, {route: 'dashboard'}); // --> <x-layout><div id="app-body"><x-page-{opts.route}></x-page-{opts.route}></div></x-layout>

// Compiles but not mounts (empty tag)
var tag = riot.tag2('x-layout', '<div id="app-body" riot-tag="x-page-{opts.route}"></div>');
riot.render(tag, {route: 'dashboard'}); // --> <x-layout><div id="app-body" riot-tag="x-page-dashboard"></div></x-layout>

// It's only working when I hard coded the tag name
var tag = riot.tag2('x-layout', '<x-page-dashboard></x-page-dashboard>');
riot.render(tag, {route: 'dashboard'}); // <x-layout><x-page-dashboard>___ CHILDREN COMPONENTS... ____</x-page-dashboard></x-layout>

Is there any possible way to implement isomorphic rendering + routing? I'm almost there, just need to pass somehow component name dynamically through opts

I finally solved it. The solution was to use name="app_body" attribute but not id="app-body" as I was trying to do.

<x-layout>
  <div name="app_body"></div>

  <script>
    this.mountPage = (page) => {
      riot.mount(this.app_body, 'x-page-' + page);
    }

    if (opts.route)
      this.mountPage(opts.route)
  </script>
</x-layout>

Thanks to GianlucaGuarini response https://github.com/riot/riot/issues/1450#issuecomment-165984208

Working example https://github.com/GianlucaGuarini/riot-app-example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM