stereobooster / react-snap

👻 Zero-configuration framework-agnostic static prerendering for SPAs
MIT License
5.05k stars 395 forks source link

Usage with loadable-componets #299

Closed yyynnn closed 5 years ago

yyynnn commented 5 years ago

Hi there!

So i'm trying to use react-snap wo SSR to prerender SPA and i have some loadable-components. Been using this entry:

...
import { loadableReady } from '@loadable/component'

const Render = () => (
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <ConnectedRouter history={history}>
        <App />
      </ConnectedRouter>
    </PersistGate>
  </Provider>
)

const rootElement = document.getElementById('app')

if (rootElement.hasChildNodes()) {
  loadableReady().then(() => {
    hydrate(<Render />, rootElement)
  })
} else {
  render(<Render />, rootElement)
}

App loads fine, but post-build with react-snap results in this error: loadableReady() requires state, please use getScriptTags or getScriptElements server-side

cant i just pre render components client side?

stereobooster commented 5 years ago

The issue is that latest loadable-components doesn't provide getState() (#297). Without it you can't use loadableReady(). So you can either downgrade loadable-components and use getState() or remove loadableReady() (which will lead to flash).

yyynnn commented 5 years ago

Yes, but when i'm using 2.2.3 with getState() i get loadable-components state not found. You have a problem server-side. Please verify that you have called loadableState.getScriptTag() server-side. error. Without loadableReady() at all, just with regular render(...) i get pageerror at /private/page/uuid: SyntaxError: Unexpected token < at path with loadable component.

loadable generator:


export const PageGenerator = ({ data }: Props) => {
  return (
    <React.Fragment>
      {data.map(({ name, id }: ComponentProps, i) => {
        const LoadableComponent = loadable(
          () => import(`lazies/${name}.lazy.ts`),
          {
            modules: [''] // Should this be used at all?
          }
        )
        return (
          <React.Fragment key={i}>
            <LoadableComponent id={id} />
          </React.Fragment>
        )
      })}
    </React.Fragment>
  )
}
stereobooster commented 5 years ago

If you use loadable-components 2.3.3 and you have something like this in index.js

import { loadComponents, getState } from "loadable-components";
window.snapSaveState = () => getState();

loadComponents()
  .then(() => hydrate(App, rootElement))
  .catch(() => render(App, rootElement));

It should work ok.

Yes modules required. Try modules: [name]

yyynnn commented 5 years ago

Ok, now it falis at loadable component pageerror at /private/page/uuid: SyntaxError: Unexpected token <

with no stack trace

stereobooster commented 5 years ago

Well, it is hard to be sure without seeing the code, but I guess it tries to load js file from the server, which in this case not js, but ts. There is no such file lazies/abc.lazy.ts, because there is lazies/abc.lazy.js as the result server returns html instead of js and this why it says SyntaxError: Unexpected token <

yyynnn commented 5 years ago

tried importing wo extension, renamed lazies to .js , app loads fine in dev, but still getting the same error. what can i provide to you to get to the bottom of this?

stereobooster commented 5 years ago

Reproducible demo, which I can download, run locally and debug

stereobooster commented 5 years ago

You can try to reproduce this error with create react app 2.1, which supports TS. At least you can crosspost to their tracker maybe they will help you

stereobooster commented 5 years ago

I will close this one for now. There is https://github.com/stereobooster/react-snap/issues/299

stereobooster commented 5 years ago

I reported issue with Suspense to React https://github.com/facebook/react/issues/14438. Let's see what they would suggest.