riot / ssr

Riot.js node Server Side Rendering
MIT License
32 stars 8 forks source link

When exporting a factory function, the components (that set in the function.components) will not be mounted. #24

Closed nibushibu closed 3 years ago

nibushibu commented 3 years ago

@GianlucaGuarini Thank you very much for resolving #23 so quickly. 🀝 I am always amazed and grateful at how fast you work.

I found another little strange behavior about this SSR module, just as the title says. I'm sorry I don't have time to share a sample that reproduces the problem yet, but let me just report it first. As soon as I have time, I will create a sample.

This problem seems to occur only with SSR modules. Also, I understand that it can be worked around by exporting normal object instead of factory function. So, I am personally not in a hurry to improve this issue.

Thank you.

GianlucaGuarini commented 3 years ago

Please make sure to create an example to reproduce the issue

nibushibu commented 3 years ago

@GianlucaGuarini I'm sorry it took me so long to provide an example. I've created a branch from my personal project that reproduces the problem, and I hope you could check it out.

https://github.com/nibushibu/Getup/tree/report-riotjs-ssr-issue-24

Steps to Reproducebec

  1. Clone the above branch
  2. npm install
  3. npm run html
  4. check dist/index.html

The result I was hoping for.

<static-component> (imported in src/html/components/html-base.riot) will be mounted

Real results

<static-component> is not mounted.

In the case of SSR, will components imported in other components not be imported? There is not much of a problem with this issue, as components imported from riot files passed directly to @riotjs/ssr render() will be mounted as expected.

GianlucaGuarini commented 3 years ago

@nibushibu your HtmlBase function should have the components static property set as described in the Riot.js documentation. Probably you have missed it https://riot.js.org/api/#componentcomponents

This patch should work

<html-base>

  <head>
    <meta charset="utf-8">
    <title>{ props.title ? props.title : state.title }</title>
    <meta if="{ props.meta }" each="{ meta in props.meta }" {...meta}>
    <meta if="{ !props.meta }" each="{ meta in state.meta }" {...meta}>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" href="{ this.props.toRoot }css/main.css">
    <script src="https://polyfill.io/v3/polyfill.min.js"></script>
    <script src="{ this.props.toRoot }js/main.js" defer></script>
  </head>

  <body>
    <h1>{ props.title ? props.title : state.title }</h1>
    <static-component></static-component>
    <slot name="default"></slot>
  </body>

  <script>
    import StaticComponent from '../components/static-component.riot'

    HtmlBase.components = {
      StaticComponent,
    }

    function HtmlBase() {
      return {
        state: {
          title: 'Static',
          meta: [
            {
              name: 'description',
              content: 'a description',
            },
            {
              property: 'og:title',
              content: 'ogp title',
            },
          ],
        },
      }
    }

    export default HtmlBase
  </script>

</html-base>
nibushibu commented 3 years ago

Thank you for taking the time to answer my questions.

And you're right, I didn't understand about component.components correctly. Your sample, which gives the expected result, has deepened my understanding. Thank you very much for always answering promptly. πŸ€˜πŸŽΈπŸš€