Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create React app with React-Snapshot Pre-Rendering static files

I'm using create react app with react-snapshot to pre-render static markup for my routes. i.e "/", "/signIn", "/signUp" generates index.html, signIn.html, signUp.htmlrespectively.

Issue I'm facing is that no matter what route I go to, initially the static index.html generated from react-snapshot for the root route "/" is served and then the correct static route file and then the main.js bundle is served(see gif). This would be fine if I was just serving my app from a bundled main.js alone. but since I want to use the static pre-generated html files, how do I disable the the service worker from serving index.html on certain routes for which I have static html file already.

Update: If I remove service worker from the create react app, the app loads static file for the path fine. However, I want to keep the functionality of service worker for PWA features.

Update 2: On chrome browser the quick flicker of root route static markup happens only once for each route. After the 1st flicker it seems the chrome browser cache fixes it, additionally if I disable cache from chrome dev tools and try to go to new route the flicker of root route returns. On Firefox browser the problem exists no matter what, on every route change or refresh the momentary flick of root route static markup occurs.

How can I avoid the index.html to be rendered initially on all routes from the service worker without removing the service worker.

In more detail:

With the Service Worker active the following code renders in the body of page source of all routes:

 <body>
 <script>window.react_snapshot_state = {};</script>
 <noscript>You need to enable JavaScript to run this app.</noscript>
 <div id="root" data-react-checksum="-928641672"><div data-reactroot="" class="sc-cSHVUG hyLStb"><div class="sc-fjdhpX dIRAsX"><ul class="sc-gqjmRU koKaUp"><li><a class="navItemActive sc-VigVT cZrGwO" href="/"><!-- react-text: 6 --> <!-- /react-text --><!-- react-text: 7 -->Home<!-- /react-text --></a></li><li><a class="sc-VigVT cZrGwO" href="/aboutUs/"> About US</a></li><li><a class="sc-VigVT cZrGwO" href="/faq/"> FAQ</a></li></ul><div class="sc-jzJRlG cLytIk"><button class="ui basic circular compact icon button sc-jTzLTM jfwzMH"><i aria-hidden="true" class="user circle icon"></i></button><button class="ui basic circular compact icon button sc-jTzLTM jfwzMH"><i aria-hidden="true" class="add user icon"></i></button></div></div><!-- react-empty: 17 --><div><div style="opacity: 1;"><div class="sc-bdVaJa eRTdVS">Home</div></div></div></div></div><script type="text/javascript" src="/static/js/main.04df5475.js"></script></body>

IF I remove the Service worker the "/signIn" route renders the following in the body of page source:

<body>
 <script>window.react_snapshot_state = {};</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root" data-react-checksum="143569200"><div data-reactroot="" class="sc-cSHVUG hyLStb"><div class="sc-fjdhpX dIRAsX"><ul class="sc-gqjmRU koKaUp"><li><a class="sc-VigVT cZrGwO" href="/"><!-- react-text: 6 --> <!-- /react-text --><!-- react-text: 7 -->Home<!-- /react-text --></a></li><li><a class="sc-VigVT cZrGwO" href="/aboutUs/"> About US</a></li><li><a class="sc-VigVT cZrGwO" href="/faq/"> FAQ</a></li></ul><div class="sc-jzJRlG cLytIk"><button class="ui basic circular compact icon button sc-jTzLTM jfwzMH"><i aria-hidden="true" class="user circle icon"></i></button><button class="ui basic circular compact icon button sc-jTzLTM jfwzMH"><i aria-hidden="true" class="add user icon"></i></button></div></div><!-- react-empty: 17 --><div><div style="opacity: 1;"><div><div class="sc-EHOje bssfxk"><div class="sc-EHOje bssfxk"><form class="ui large warning form sc-ifAKCX ljuaXJ"><div class="field"><label></label><input type="email" placeholder="email" name="email" value=""></div><p class="sc-bxivhb dXOlfT">error</p></form><form class="ui large warning form sc-ifAKCX ljuaXJ"><div class="field"><label></label><input type="password" placeholder="password" name="password" value=""></div><p class="sc-bxivhb dXOlfT">error</p></form></div><p class="sc-dnqmqq ccTWaR"></p><div><div class="sc-gzVnrw cCgvhR"><button class="ui basic button sc-iwsKbI Vfjvd"><!-- react-text: 37 -->Login<!-- /react-text --><!-- react-text: 38 --> <!-- /react-text --></button><div class="sc-gzVnrw cCgvhR"><!-- react-empty: 40 --><div class="ui horizontal divider" style="width: 220px;">Or</div><div class="sc-bZQynM kECAnI"><button class="ui google plus button" style="text-transform: capitalize;"><i aria-hidden="true" class="google icon"></i><!-- react-text: 45 --> Google<!-- /react-text --></button><button class="ui facebook button" style="text-transform: capitalize;"><i aria-hidden="true" class="facebook icon"></i><!-- react-text: 48 --> Facebook<!-- /react-text --></button></div></div></div><div><p class="sc-htoDjs dErAlA">forgot your password ?</p></div></div></div></div></div></div></div></div><script type="text/javascript" src="/static/js/main.04df5475.js"></script><iframe style="display: none;"></iframe>

GiF shows me trying to access "/signIn" Route, and notice the word home (static markup for "/" route) come up for a moment before the actual form for "/signIn" route renders.

enter image description here

like image 960
jasan Avatar asked Sep 14 '17 08:09

jasan


People also ask

Can a react app be static?

React-Static is a fast, lightweight, and powerful progressive static site generator based on React and its ecosystem. It resembles the simplicity and developer experience you're used to in tools like Create React App and has been carefully designed for performance, flexibility, and user/developer experience.

Does react pre render?

react-snap is a third-party library that pre-renders pages on your site into static HTML files.

Does react build a static site?

React-static is a progressive static site generator based on React and its ecosystem. Because it is powerful, lightweight, and fast, it will be a great option for your next React app. React-static has been carefully designed for user/developer experience, flexibility, and performance.


1 Answers

The issue was that Service Worker(SW) by default in Create React App only caches contents of static folder and the index.html. My pre-rendered .html files from react-snapshot were never cached by the SW. the SW in create react app also is set to serve index.html for all unknown urls, thus it was serving the root path "/" static file index.html. I solved this by overwriting the service-worker.js file by changing the build command in package.json like so:

"build": "react-scripts build && react-snapshot && sw-precache --config=sw-precache-config.js"

where my sw-precache-config.js looked like the following:

module.exports = {
  staticFileGlobs: [
    './build/**/**.html',
    './build/images/**.*',
    './build/static/**',
  ],
  dontCacheBustUrlsMatching: /\.\w{8}\./,
  swFilePath: './build/service-worker.js',
      // For unknown URLs, fallback to the index page
  navigateFallback: './200.html',
      // Ignores URLs starting from /__ (useful for Firebase):
      // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
  navigateFallbackWhitelist: [/^(?!\/__).*/],
      // Don't precache sourcemaps (they're large) and build asset manifest:
  staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
  stripPrefix: './build'
}
like image 84
jasan Avatar answered Sep 30 '22 11:09

jasan