1

I created a project with React, react-router, @loadable/component.

Now I'm trying to add SSR to this project. I did server side rendering with react-router.

And then I added @loadable/component to import all pages component:

import loadable from '@loadable/component';

const routersConfig = [
  {
    path: '/',
    component: loadable(() => import('./Home')),
    exact: true,
  },
  {
    path: '/2',
    component: loadable(() => import('./Home2')),
    exact: true,
  },
];

Then I added all this parts of code: https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/

And now it works. But It works with the problem: a content blinks while loading.

How I understand the page's loading process:

  1. Browser gets a content generated by SSR (the first query in network tab)
  2. Browser renders a content (with left and top margins )
  3. Browser downloads two enterpoints and vendors from html (app.js, normalizer.js, vendor.js)
  4. Browser executes app.js and normalizer.js. Left and top margins are removed.
  5. App.js starts downloading page's chunk - home.js. In this moment content disappears
  6. When home.js is downloaded, the content appears again.

I shoot a video to illustrate this process. (I'm sorry for quality, stackoverflow forbides files which size is more then 2MB ). I'm throttling network speed to imagine all page's download process.

enter image description here

My question is why the content disappears? How to fix it?

My code

server.js

const sheetStyledComponents = new ServerStyleSheet();
  const sheetsJssRegistry = createSheetsRegistry();
  const statsFile = path.resolve(process.cwd(), './build-ssr/dist/loadable-stats.json');

  const extractor = new ChunkExtractor({
    statsFile,
    entrypoints: [
      'app',
      'normalize',
    ],
  });


  try {
    const client = ApolloSSRClient();

    const tree = (
      <ApolloProvider client={client}>
        <ApplyTheme sheetsRegistry={sheetsJssRegistry}>
          <StaticRouter location={req.url}>
            <Home />
          </StaticRouter>
        </ApplyTheme>
      </ApolloProvider>
    );

// there is combination of Apollo graphql, jss, styledComponent functions
    const body = await getMarkupFromTree({
      renderFunction: flow(
        sheetStyledComponents.collectStyles.bind(sheetStyledComponents),
        extractor.collectChunks.bind(extractor),
        renderToString
      ),
      tree,
    });

    const scriptTags = extractor.getScriptTags(); 
    // It isn't used yet
    const linkTags = extractor.getLinkTags(); 

    const styleTags = sheetStyledComponents.getStyleTags();

    const html = (await rawHtml)
      .replace(
        '</head>',
        ` 
          ${styleTags}
          <style type="text/css" id='jss-server-side-styles'>
              ${sheetsJssRegistry.toString()}
          </style>
          <script>
            window.__APOLLO_STATE__ = ${JSON.stringify(client.extract())};
          </script>
          ${scriptTags}
          </head>
        `
      )
      .replace('<div id="app"></div>', `<div id="app">${body}</div>`);


    res.send(html);

index.jsx

const SSRApp = (
  <ApolloProvider client={ApolloClient}>
    <ApplyTheme>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </ApplyTheme>
  </ApolloProvider>
);

loadableReady(() => (
  ReactDOM.hydrate(
    SSRApp,
    document.getElementById('app'),
  )
));
Oleg
  • 1,048
  • 1
  • 9
  • 18
  • Can we see your component as well as the code where you are using ReactDOM? I think that might help a bit more. – Joshua Blevins Jul 16 '19 at 14:11
  • 2
    As far as I can understand your js code reap out everything inside `
    `and render it from scratch. In theory your js shouldn't do that it should connects to existed components inside that `
    `
    – Arseniy-II Jul 16 '19 at 14:29
  • After reading the documentation on react-router's github repo, we really need to see where your Router is defined, as well as how it is defined. – Joshua Blevins Jul 16 '19 at 14:35
  • @JoshuaBlevins thank you for answer. I have added some code – Oleg Jul 16 '19 at 15:26
  • @Arseniy-II I think so. But why does my code do this?) – Oleg Jul 16 '19 at 15:27
  • 1
    I believe your entire web page is blinking because the entire page is wrapped within which changes the content when you navigate to another page. If you want the header to not blink, you need to move the Header outside of your component. Try that and let me know the results. I am interested in your setup. – Joshua Blevins Jul 16 '19 at 15:42
  • 1
    @JoshuaBlevins I have found error. It's just trying to render SSR instead of . You can see it in my code. – Oleg Jul 17 '19 at 05:59
  • That makes sense. I am glad that you figured everything out. – Joshua Blevins Jul 17 '19 at 18:44

2 Answers2

2

It was my fault.

The hydration version of app contained BrowserRouter -> Switch -> Router -> HomePage

And the SSR version contained only StaticRouter -> HomePage

Because of this, after rendering SSR version, react removed all DOM and created new one with Router.

Oleg
  • 1,048
  • 1
  • 9
  • 18
0

i changed in server.js. its worked for me

yours maybe (server/index.js or server.js or server/app.js..etc)

import Express from 'express';
import Loadable from 'react-loadable';

// from //


  app.listen(3000, () => {
    console.log('app now listening on port', port);
  });


// to //

  import Loadable from 'react-loadable';

  Loadable.preloadAll().then(() => {
     app.listen(port, () => {
     console.log('app now listening on port', port);
   });
  });

for more config understanding you can see

The first step to rendering the correct content from the server is to make sure that all of your loadable components are already loaded when you go to render them.

To do this, you can use the Loadable.preloadAll method. It returns a promise that will resolve when all your loadable components are ready.

D V Yogesh
  • 3,337
  • 1
  • 28
  • 39
  • loadable component. doesnt have anything like that but i'm facing the blink . there is nothing to wrap `app.listen` in loadable components either. – zahra shahrouzi Feb 04 '21 at 13:50