React server and client rendering - reactjs

Using https://github.com/ayoubdev/reactjs-isomorphic-starterkit as a boiletplate.
I'm trying to figure out how to inject the client's bundle into the server rendering process.
As the webpack build for server and client is well separated, is there a simple trick to achieve this goal ?
Thanks

I'm not too sure about the specifics of this boilerplate repo. But I can try to explain the main idea, and you can dig deeper.
The basic idea is, use a bundler (in this case, webpack is used, gulp, grunt, whatever else is fine as long as you transpile) and build a bundle based on the entry point for your React components. Then link this bundle via script tag in some html file.
For the server side, you can use ReactDOMServer.renderToString. Import your component(s), pass them into ReactDOM.renderToString. Pass the HTML to some templater like ejs or use a raw HTML string and call React.render from the server.
Client side.
In your example, the entry point is here and hooked here. Notice the <div class= "app"> tag. This is tag we are referencing in our entry point. We also reference our bundled js from webpack via script tag, client.bundle.js.
Server side
In your example, the relevant code is here. Notice the renderComponent function. It builds a string based on the HTML of the component supplied from ReactDOMServer.renderToString, which is called on Line 39. It then sends all of that html back as a response in res.send
This blog article uses jade as an example, which you can use as an alternative if you find this boilerplate a bit much.

Related

React use route from Express instead of index.html

I have a React application running on port 3000, I have an express backend running on port 5000. I would like React to instead of using index.html as the base HTML for the application to instead call port 5000 and use that html (I have a route there, index.html that when I do localhost:5000/index.html responds correctly). How can I tell React to not look in the public/index.html and instead pull it from the backend?
I think you could minimize this kind of problem by using everything in just one project.
The thing is that, you need a mount point for your React app. So, you could fetch for what it's in localhost:5000/index.html (you may need to enable CORS), and obviously you should use DOM Parser to parse the incoming response to text, and then to a manipulable DOM, after that find a mount point element for your application, and finally render everything as a string in your current html document.
So, you'd need to do something like this; and then using a querySelector to find the mount point in you application, and then use DOMParser to render.
However, you'd need to have an arquitecture in which every component you're using in your application is provided. You may need to use react-router so this is achieved.
You can do this with a proxy and CORS.
In your React app in your package.json you can specify
"proxy": "http://localhost:5000"
You should also install the CORS library on your express server

Sharing on social media, the URL does not render any meta data

We have built a project (Web Application) in React .net core using react in client-side rendering.
We've used react-helmet for dynamically assigning meta tags.
The issue being when the app renders in the browser. The browser gets only the static HTML on initial load which does not include the dynamic meta tags we have set. However on inspecting you get those meta tags under "Elements".
Also, if we use these URL for sharing on any social media, like WhatsApp or Facebook, the URL does not render any metadata as it should.
Tried searching for solutions to our problem, the most obvious answer we came across was to try server-side rendering instead. We get that, but it is not a solution to try out at this juncture when we're ready with app to roll it out.
Others we came across were "react-snap", "react-snapshot", but no luck
with react-snap, it requires to upgrade React's version to 16+, which we did but I guess not all dependencies were upgraded, there was an error saying "
hydrate is not a function
(hydrate concerns the react-dom)
With react-snapshot, we could not find the necessary type definition, which is required in react .net core to function properly
Please guide for the next probable step (except the paid ones like prerender, etc)?
Main goal: Social Applications should render the meta data when we paste/share the URL within them.
Prerender is the only solution.
I used a node dependency called "prerender" -> https://github.com/prerender/prerender
It works enabling a web server wich make http requests. Assigning value to a boolean: window.prerenderReady = true; in your website tells your server when the page is ready to "take the photo" and it returns the Html when so. You need to program an easy script that parses all the site urls and save those html contents to files. Upload them to your server and using .htaccess or similar target the crawlers external-hit-facebook,twitterbot,googlebot, etc.. to show them the prerendered version and 'the real site' to the rest of user-agents.
It worked for me.
The meta tags for Open Graph need to be present in the HTML which is sent back to the client when fetching a URL. Browsers or bots will not wait until the app is rendered on the client side to determine what the metatags are - they will only look at the initially loaded HTML.
If you need the content of your Open Graph metadata to be dynamic (showing different content depending on the URL, device, browser etc.) you need to add something like react-meta-tags into your server code.
There are no type definitions available for any of the react meta tags libraries, but you can add your own. It can be a bit tricky, but check out the official documentation and the templates they have provided to get started.
If you don't need it to be dynamic, you could add the tags into the static parts of the <head>-tag in your index.html.
I had the same issue today. I had two React Web applications that need this. Here is how I solved it:
put your preview image in the public folder
still in public folder, Open index.html, add the line <meta property="og:image" content="preview.png"/>
or <meta property="og:image" content="%PUBLIC_URL%/preview.png"/>.
Go to https://www.linkedin.com/post-inspector/ to check if it works.
I hope this would help!

How to tell React to use another index

I created an app with
react-create-app client
inside my e-commerce website(it uses nodejs and express), in order to implement some other functionalities. The problem is that i don't understand how to make the react-app work with ejs template, instead of using index.html. First of all i want the root component to be in a .ejs file inside views folder(outside react app). I think i need to change something in webpack, but i'm really confused, i can't even find config and there are a lot of additional plugins and code that i've never seen before, it's really difficult to understand something. Also when i run my server on port 3000 and app on port 5000 (with proxy set on 3000) it says 'something already running on port 3000'. What should i do? I can't use react on the entire website (all buttons, menus) because it's too simple for react i think, and there is some simple rendering done with ejs that i don't know how to implement with react.
At first you shouldn't use create-react-app for just bunch of components on existing page, this is whole environment done for true SPA done purely in React. If you need to just plug React to the existing page you have no choice than to read docs and learn or find a way how to setup in your existing app (you didnt say anything about it so I am not answering how.)
Secondly you need to eject your react app with yarn eject which will expose you all configs. https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject
Then you need html-webpack-plugin which can accepts .ejs format as entry point https://github.com/jantimon/html-webpack-plugin.
I don't see any reason why not to use React for everything, because it is "too" simple. You can render plain HTML with PureComponents and it will cost almost 0 memory for browser to render it.

"React attempted to reuse markup" error with webpack + code splitting

I've started implementing code splitting in an "universal" app (react-router, redux, webpack - largely based on https://github.com/erikras/react-redux-universal-hot-example).
On the (only) route where code splitting is implemented, I am getting the following React error message when doing a full browser refresh:
warning.js:44Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <!-- react-empty: 1 -
(server) <div class="root" dat
If I disable code splitting, the error message goes away. I am guessing this is due to React doing a first render before the Javascript chunk was loaded by the Webpack loader and therefore, it generates markup that is different from the one generated on the server. Is that correct?
Should I worry about the error message?
Any way to figure out what React renders to at the exact time this message occurs?
Any fix to make the message go away? (other than to not use code splitting)
The solution is to call react router's match function before doing the first render.
See https://github.com/reactjs/react-router/issues/2036#issuecomment-225792937 and https://github.com/reactjs/react-router/blob/v2.4.1/docs/guides/ServerRendering.md#async-routes
Should I worry about the error message?
Yes, if React determines the mark-up differs it'll fail to re-use any of the existing mark-up and instead re-generate it from the client render resulting in more work for the browser.
Any way to figure out what React renders to at the exact time this message occurs?
You can compare the differences by diffing the generated source in dev tools and the html sent over the network.
Any fix to make the message go away? (other than to not use code splitting)
You could call match as you've suggested in your answer or alternatively, if you happen not to be using React Router or your split points aren't setup via the router you could load all required chunks up front, e.g.
<!-- index.html -->
<script src="entry.js"></script>
<script src="chunk1.js"></script>
<script>
// NOTE: Instead of calling render immediately in `entry.js` you would need to define a function on the global to allow you to render the app after the second chunk has loaded.
window.App.render();
</script>
NOTE: This would only work when using require.ensure because System.import / import is always async which would mean the mark-up would still differ on the very first render.

AngularJS export html to pdf with css

I have a task where I need to export the html to pdf. Where the pdf should have the same design as it has in browser. Basically I need the css should also work in pdf file. Am using angularjs for front end. But I have not found any use full module or any js library which supports my requirement. I also need to update AngularJS scope variables values in pdf. I found one http://pdfmake.org/#/ but it only supports some predefined css attributes. Please provide some suggestion if there is some npm module or any js library which render the html to pdf with css.
Thank you
I am not sure if there is a fully featured JavaScript solution, which can convert HTML/CSS to PDF on client side. It makes sense to take a look to server-side solutions - there are many available.
In an "hybrid" scenario on client side you'd need to populate a HTML/CSS template with variable values, send the resulting HTML/CSS doc to the server side and to receive back a generated PDF.
In the case it is not important anymore, if the converter is written in JavaScript. You may use a standalone native applications, utilize print/PDF output subsystem of WebKit (i.e. PhantomJS) or it can be, for example, a Java module deployed to your application server (i.e. PD4ML).

Resources