Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server side rendering #1236

Closed
wants to merge 106 commits into from
Closed

Server side rendering #1236

wants to merge 106 commits into from

Conversation

tomazy
Copy link
Contributor

@tomazy tomazy commented Nov 15, 2016

Implements #1103

I've managed to extract the SSR code from one of our apps based on this boilerplate.
There are still a few issues to fix (see below) but I thought I could ask you guys to help me with reviewing it.

I'm including the CSS during the server side rendering but the styled components inject it anyway. It would be great if we could avoid it. Any ideas? Is there any "virtual-css" yet :) ?

TODO

  • Use hashes in assets' names (vendor.css, main.js)
  • Fix the content flash (this is not FOUC, but for some reason there is an ugly blink)
  • Tests
  • Split dev/production middlewares into separate modules
  • Handle 404
  • npm run clean
  • How do people with JS disabled access the german version?
  • npm run generate route

@coveralls
Copy link

coveralls commented Nov 15, 2016

Coverage Status

Coverage decreased (-19.0%) to 79.643% when pulling 4d0f416 on tomazy:ssr into 33485f4 on mxstbr:dev.

@coveralls
Copy link

coveralls commented Nov 15, 2016

Coverage Status

Coverage decreased (-19.0%) to 79.643% when pulling 4d0f416 on tomazy:ssr into 33485f4 on mxstbr:dev.

@coveralls
Copy link

coveralls commented Nov 16, 2016

Coverage Status

Coverage decreased (-15.2%) to 83.395% when pulling cab9cb5 on tomazy:ssr into 33485f4 on mxstbr:dev.

@coveralls
Copy link

coveralls commented Nov 16, 2016

Coverage Status

Coverage decreased (-15.2%) to 83.395% when pulling 8214e03 on tomazy:ssr into 33485f4 on mxstbr:dev.

@coveralls
Copy link

coveralls commented Nov 16, 2016

Coverage Status

Coverage decreased (-15.2%) to 83.395% when pulling 68457b7 on tomazy:ssr into 33485f4 on mxstbr:dev.

@kunal-arora
Copy link

yes I did that.

@philipcressler
Copy link

@tomazy When I pull your SSR branch, I'm getting the following errors on page load:

screen shot 2017-10-13 at 1 22 17 pm

Any idea how to fix? Thank you for your effort in creating an SSR branch of this great boilerplate.

@nhducit
Copy link

nhducit commented Oct 14, 2017

@philipcressler #1901

@juciccio
Copy link

Hey guys, does someone have an example of how to add server side rendering? I have a project made with version 3.4 and I need server side meta tags for Facebook and Twitter sharing.

@hadifarnoud
Copy link

you're not alone @juciccio. if anyone writes a comprehensive tutorial, that would be awesome!

@davidjbradshaw
Copy link

@juciccio & @hadifarnoud I expect the easiest solution would be to create a new project based on this branch, then lift and shift your project code into it.

The other option would be to merge this branch into your project, but I expect you will have a lot of conflicts to resolve in code that your not familiar with.

@nhducit
Copy link

nhducit commented Dec 13, 2017

I integrated this branch to react-boilerplate 3.4 project and this is exact what I did.

@juciccio & @hadifarnoud I expect the easiest solution would be to create a new project based on this branch, then lift and shift your project code into it.

@hadifarnoud
Copy link

if a few of us (I'm not a react developer myself but will make sure our dev join the effort) maintains a forked copy of this boilerplate with ssr, that would be much appreciated since @tomazy is not updating it anymore.

ssr is an important feature for a lot of us. still hope @mxstbr and maintainers of this repo reconsider.

@nhducit
Copy link

nhducit commented Dec 14, 2017

ssr is an important feature for a lot of us. still hope @mxstbr and maintainers of this repo reconsider.

I agree, but SSR is really a big and complex PR. if we official support it then we need to do benchmarks and you can see we lack of maintainer add SSR even make this project hard to maintain.
btw next.js is really good project and well maintained

@ItsMrAkhil
Copy link

@nhducit
I agree SSR is complex. But at least for the first attempt if we can ignore the hot reloading with SSR we may do it.
Or else let's restrict the SSR for some routes. We can keep a config file where we can have regex. only for those routes activate SSR that to only in production mode. (So no Hot reloading no hot module replacement. No server restart.)
I don't know whether this is a good idea or not. But I think it is possible.

@arthurCormack
Copy link

I've used this SSR as the foundation of a couple production sites now, and I'm pretty happy with the results so far. http://classicalfm.ca is one of them. I integrate a wordpress json api, for content, and return appropriate http codes (200, 301, and 404s) from the SSR based upon calls to the content api.

@zalabinc
Copy link

zalabinc commented Dec 19, 2017

I tried to combine this project structure in order to run in next.js
I do not do much change, file structure for this RB project is ideal for scalling.
I've used this code structure as the foundation with nextJS,

Work like charm 👍
React Boilerpate + NextJS = 🥇

https://github.com/zalabinc/nextjs-boilerpate/blob/master/app/utils/configureStore.js

@ItsMrAkhil
Copy link

@zalabinc Good attempt.

@hadifarnoud
Copy link

it would be great if someone creates a clean fork with latest version of RB merged. there are enough people here willing to put time in maintaining it.

@davidjbradshaw
Copy link

@hadifarnoud that sounds very close to volunteering to take it on.

@hadifarnoud
Copy link

I'd love to @davidjbradshaw but I'm not a developer myself. I would've done it long ago if I could

@hadifarnoud
Copy link

all the ssr tasks in package.json are run in NODE_EVN=development. should I change them to production? why was it set to dev anyway?

@tomazy
Copy link
Contributor Author

tomazy commented Dec 27, 2017

@hadifarnoud They are there to support hot reloading etc and you don't need that in production

@hadifarnoud
Copy link

thanks @tomazy , can you post the recommended production version here please?

@tomazy
Copy link
Contributor Author

tomazy commented Dec 28, 2017

@hadifarnoud You just use the default scripts as documented:

npm run start:production - this will run all the tests, build the assets and start the server.

If you only care about building the assets before deployment to a target server then run:

npm run build

and on the target server:

npm run start:prod.

You don't need to do anything special to enable SSR in production. It should just work.

@juciccio
Copy link

juciccio commented Jan 5, 2018

I was using react-boilerplate 3.4 with postcss and now I integrated this branch to my project, everything works fine but now i can't have css in each component the imports are not working anymore. Any suggestion?

@kunal-arora
Copy link

kunal-arora commented Feb 25, 2018

Hello everyone, I have 2 questions related to routes, my routes.js file looks like this

// These are the pages you can go to.
// They are all wrapped in the App component, which should contain the navbar etc
// See http://blog.mxstbr.com/2016/01/react-apps-with-pages for more information
// about the code splitting business
import { getAsyncInjectors } from 'utils/asyncInjectors';
import App from 'containers/App';

const errorLoading = (err) => {
  console.error('Dynamic page loading failed', err); // eslint-disable-line no-console
};

const loadModule = (cb) => (componentModule) => {
  cb(null, componentModule.default);
};

function createChildRoutes(store) {
  // create reusable async injectors using getAsyncInjectors factory
  const { injectReducer, injectSagas } = getAsyncInjectors(store); // eslint-disable-line no-unused-vars
  let previousPath = null;
  return [
    {
      path: '/',
      getComponent(nextState, cb) {
        if (nextState.location.pathname === previousPath) {
          return;
        }
        const importModules = Promise.all([
          import('containers/HomePage/reducer'),
          import('containers/App/sagas'),
          import('containers/HomePage/sagas'),
          import('containers/HomePage'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([reducer, appSagas, sagas, component]) => {
          injectReducer('homePage', reducer.default);
          injectSagas([...appSagas.default, ...sagas.default]);

          renderRoute(component);
        });

        importModules.catch(errorLoading);
        previousPath = nextState.location.pathname;
      },
    },
    {
      path: '/:urlKey',
      getComponent(nextState, cb) {
        if (nextState.location.pathname === previousPath) {
          return;
        }
        const importModules = Promise.all([
          import('containers/CatalogPage/actions'),
          import('containers/CatalogPage/reducer'),
          import('containers/App/sagas'),
          import('containers/CatalogPage/sagas'),
          import('containers/CatalogPage'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([actions, reducer, appSagas, sagas, component]) => {
          injectReducer('catalogPage', reducer.default);
          injectSagas([...appSagas.default, ...sagas.default]);
          renderRoute(component);
          store.dispatch(actions.loadPageData(nextState.params.urlKey));
        });

        importModules.catch(errorLoading);
        previousPath = nextState.location.pathname;
      },
    }, {
      path: '*',
      getComponent(nextState, cb) {
        import('containers/NotFoundPage')
          .then(loadModule(cb))
          .catch(errorLoading);
      },
    },
  ];
}

// Set up the router, wrapping all Routes in the App component
export default function createRootRoute(store) {
  return {
    component: App,
    childRoutes: createChildRoutes(store),
  };
}

First, path: '/:urlKey', this path is getting called even if I am on my homePage i.e localhost:3000/ and if i console the path it show /null or sometimes /false. How should I prevent that from happening ?

Second, how to block store.dispatch(actions.loadPageData(nextState.params.urlKey)); on the initial render of the app ?

@gretzky
Copy link
Member

gretzky commented Mar 2, 2018

Closing this PR because it's gone off track and is out of date. Please feel free to open a new PR based on SSR discussion in #1103

@gretzky gretzky closed this Mar 2, 2018
@lock
Copy link

lock bot commented May 28, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators May 28, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet