Khan / aphrodite

Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation
5.34k stars 188 forks source link

aphrodite SSR style break on style tag update #376

Open Maliqureshi33 opened 5 years ago

Maliqureshi33 commented 5 years ago

Hello the Devs of aphrodite this is indeed a great lib to write CSS in JS and I am using it in my SSR application created in razzle. but as I move forward I am having an issue when I a, trying to use another lib that uses aphrodite (older version). the lib function triggers an update in the style data-aphrodite tag and breaks the style (although all is still written in the same style tag). apart from using the lib event to trigger a style tag change, when I try to edit the style tag the style breaks even then too, although no change has been made to any style from my end.

server.js

  i18n
.use(Backend)
.use(i18nextMiddleware.LanguageDetector)
.init(
  {
    debug: false,
    preload: ['en-US', 'ar-SA'],
    ns: ['translations'],
    defaultNS: 'translations',
    backend: {
      loadPath: `${appSrc}/locales/{{lng}}/{{ns}}.json`,
      addPath: `${appSrc}/locales/{{lng}}/{{ns}}.missing.json`,
    },
    keySeparator:"->",
    fallbackLng:'en-US',
    detection : detectionOption,
  },
  () => {
    server
      .disable('x-powered-by')
      .use(i18nextMiddleware.handle(i18n))
      .use('/locales', express.static(`${appSrc}/locales`))
      .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
      .use(require('./static.js'))
      .post("/locales/add/:lng/:ns", i18nextMiddleware.missingKeyHandler(i18n))
      // .get("/locales/resources.json", i18nextMiddleware.getResourcesHandler(i18n))
      .get('/*', (req, res) => {
        const extractor = new ChunkExtractor({
          statsFile: path.resolve(__dirname + '/loadable-stats.json'),
          entrypoints: ['client'],
        })
        const context = {};
        const data = StyleSheetServer.renderStatic(
          () => renderToString(
            <ChunkExtractorManager extractor={extractor}>
              <Provider store={store}>
                <I18nextProvider i18n={req.i18n}>
                  <StaticRouter context={context} location={req.url}>
                    <App />
                  </StaticRouter>
                </I18nextProvider>
              </Provider>
            </ChunkExtractorManager>
          ));

        if (context.url) {
          res.redirect(context.url);
        } else {
          const initialI18nStore = {};
          req.i18n.languages.forEach(l => {
            initialI18nStore[l] = req.i18n.services.resourceStore.data[l];
          });
          const initialLanguage = req.i18n.language;
          res.status(200).send(
            `<!doctype html>
              <html lang="">
              <head>
                  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
                  <meta charset="utf-8" />
                  <meta name="viewport" content="width=device-width, initial-scale=1">
                  <link href="/css/mapbox-gl.css" rel="stylesheet" />
                  ${assets.client.css ? `<link rel="stylesheet" href="${assets.client.css}">` : ''}
                  ${extractor.getLinkTags()}
                  ${extractor.getStyleTags()}
                </head>
                <body oncontextmenu="return false;">
                  <div id="root">${data.html}</div>
                  ${extractor.getScriptTags()}

                  <script src="/js/jquery-3.3.1.slim.min.js"></script>
                  <script src="/js/popper.min.js" ></script>
                  <script src="/js/bootstrap.min.js"></script>
                  ${process.env.NODE_ENV === 'production' ? `<script src="${assets.client.js}" defer></script>` : `<script src="${assets.client.js}" defer crossorigin></script>`}
                  <script>

                  window.renderedClassNames = ${JSON.stringify(data.css.renderedClassNames)};
                  </script>
                  <script>
                  window.initialI18nStore = JSON.parse('${JSON.stringify(initialI18nStore)}');
                  window.initialLanguage = '${initialLanguage}';
                  ReactDOM.render(<App/> , document.getElementById('root'))
                  </script>
                <style type="text/css" data-aphrodite>${data.css.content}</style>

              </body>
            </html>`
          );
        }
      });
  })

Client.js

  const BaseApp = () => {
    useSSR(window.initialI18nStore, window.initialLanguage);
    return (
      <Suspense fallback={<div/>}>
        <Provider store={store}>
          <BrowserRouter>
            <App />
          </BrowserRouter>
        </Provider>
      </Suspense>
    );
    StyleSheet.rehydrate(window.renderedClassNames);
  }
  loadableReady(() => {

    hydrate(
      <BaseApp/>,
      document.getElementById('root')
    );  
  })

  if (module.hot) {
    module.hot.accept();
  }