gawati / gawati-portal-ui

Version 2 of the gawati portal
GNU Affero General Public License v3.0
0 stars 0 forks source link

SEO and Performance Optimized Portal UI #1

Open kohsah opened 6 years ago

kohsah commented 6 years ago

Implement server side rendering. Currently the page javascript is loaded, and then the page requests the service for data - this is the norm for Ajax Async applications. If the request is made prior to the load of the page (i.e. on the server) then the request bottle is eliminated on the client.

Current gawati-portal-ui design is server-less and produces a static build which is then deployed onto Apache, this may need to change. Portal-ui uses create-react-app, we should avoid "ejecting" this option, some links below show server side rendering without ejecting.

See : https://donejs.com/ssr-react.html https://medium.com/@cereallarceny/server-side-rendering-with-create-react-app-fiber-react-router-v4-helmet-redux-and-thunk-275cb25ca972

kohsah commented 6 years ago

See also:

with create-react-app without ejecting:

  1. https://medium.com/bucharestjs/upgrading-a-create-react-app-project-to-a-ssr-code-splitting-setup-9da57df2040a
  2. https://github.com/cereallarceny/cra-ssr

static generator approach:

https://www.gatsbyjs.org/blog/2017-09-18-gatsby-modern-static-generation/

Using webpack without ejecting:

https://blogs.msmvps.com/theproblemsolver/2017/11/26/react-server-side-rendering-with-webpack/

Another approach, but adds a wrapper on CRA

https://vfeskov.com/2017/12/29/Create-React-App-with-SSR-and-Service-Worker/

Currently portal-ui is serverless (i.e we build and deploy as static html )... it wont be with Server side rendering.

kohsah commented 6 years ago

This optimization is being handled in 2 parts:

  1. Use code splitting to improve page load times (this is primarily optimization of the way in which the items are loaded in the browser)
  2. Migrate to next.js which is a framework that supports SSR out of the box. SSR will result in some performance improvement, and better SEO .
kohsah commented 6 years ago

code splitting - pending test and merge

ashwinibm commented 6 years ago

Issues while trying to migrate Footer and HomeContentArea to Next.js:

  1. css custom properties are not getting applied e.g. var(--footer-bg-color). This is after using next-css plugin and making the necessary config updates.
  2. Can't pass variables to dynamic imports. i.e dynamic(import(${path})) does not work
  3. Routes need to be parameterized. Wild cards in the server don't seem to work either. e.g: localhost:3000/content/_lang/en/_page/policies needs to be localhost:3000/content?_lang=en&_page=policies to get the _lang value. Was able to pass the route props.
  4. i18n related changes. Need to get the 'T' function without having to pass it down in props every time.
  5. Next.js does not have React Router's Switch equivalent. This would imply significant restructuring.

Axios fails in HomeContentColumn : axios.get(apiRecentSummary) But get from the same url works in page/home. Only difference is that home.js is a Page and HomeContentColumn is a React component.

kohsah commented 6 years ago

@ashwinibm I checked out the code, i have an idea why the axios request may be failing, i dont think its because of page v/s component. see constants.js:

export const dataProxyServer = () => 
    process.env.NODE_ENV === 'development' ? "" : gawati().GAWATI_PROXY ;

In CRA there is a proxy config in package.json ... where CRA proxies all requests to the data API (in development mode) . So instead of querying localhost/gwd/blah/blah ... it does localhost:3000/gwd/blah/blah . This is just a ease of use thing, otherwise you need to configure CORS headers on the data API server. So I think changing that API to just return GAWATI_PROXY should fix that for now (unless there is a similar proxy config for next.js). If you do that then you need to add CORS headers to your apache http config for the virtualhost.

One other thing , the gawati() function is just a wrapper on a global construct:

export const gawati = () => window.gawati ;

Where window.gawati is set in public/index.html. This is a way to have a system-wide parameter in client-side React . Not sure this file is being used in next.js .. so that global gawati() may not be there in next.

    <script>
      gawati = {
        GAWATI_PROXY: "http://localhost",
        GAWATI_DOCUMENT_SERVER: "http://localhost"
      };
      </script>
ashwinibm commented 6 years ago

@kohsah CORS solved the issue. I managed to get styles working. The custom css variables required postcss-loader with a postcss plugin - postcss-css-variables. However, we need to declare all the variables at compile time. How do we support theme changes? I might be missing something here because CRA does not use the plugin (although it does use postcss-loader).

kohsah commented 6 years ago

@ashwinibm @Arunadevi If you see in the portal-ui App.js:

there is componentDidMount():

  componentDidMount() {
    if (process.env.NODE_ENV === 'development') {
      const path =  './css/themes/' + process.env.REACT_APP_THEME + '/vars.css';
      import(`${path}`);
    }
  }

we import() the CSS at runtime (i would say build time since REACT_APP_THEME is set during the build) to set the active theme. vars.css has a set of css custom properties which allow customizing aspects of the UI.

Does that answer your question ?

ashwinibm commented 6 years ago

Another thing to keep in mind: Next executes server side first and then client side. So any access to the 'window' object must be present only on the client side or within componentDidMount. External client only components need to wrapped - https://github.com/kadirahq/react-no-ssr

kohsah commented 6 years ago

@ashwinibm yeah window won't be there on the server side, so we perhaps need a JSON which is the base config used by the Server side, and is available client side on the window object at least for those two params.

ashwinibm commented 6 years ago

Yes, I had seen that. However, just importing that didn't apply the values. Could it be because the page is getting rendered server side? next-css bundles everything into styles.css where it applies all the vars. And we need to provide a link in the head tag: <link rel="stylesheet" href="/_next/static/style.css" />

kohsah commented 6 years ago

@ashwinibm The thing is css custom properties is a client side thing, as long as it is served onto the browser and the browser supports it (chrome, firefox, edge etc. support it) it will get applied. I suspect there is some other post-css voodoo being applied here which is changing the previous default behavior in some way.

kohsah commented 6 years ago

@ashwinibm I think we need to use this postcss plugin for var() to work : http://cssnext.io/