Static site generator that renders React to HTML directly (no React in output)? - reactjs

Can Gatsby or Jekyll or any other static site generators render a React-authored site into purely static HTML? I'm looking to host on S3/CloudFront or similar and also have little to no JS in the output.
Basically I'm looking to create a static website but would like to use React as development tool to take advantage of reusable UI components. Actual runtime interaction is minimal and can be done without React at runtime.
I looked at react-static which seems to be exactly what I'm looking for but the rendered html pages still reference and load the React library.
With my minimal needs I could probably roll my own thing to create each page as a separate React SPA and then use ReactDOMServerto render each to a static HTML file. I'm looking to see if there are simpler/better options.

You can use pupeteer to get the rendered html of any webpage, including SPA. Or use rendertron, which uses pupeteer underneath.
Another one is react-snap, which will crawl your web on build and create the html for each page.

With Gatsby, sure you can. Gatsby has a html.js that serves as a template for all generated pages. You can simply remove Gatsby's javascript from that html.
/* Generated html */
...
<body>
<div id="___gatsby">...</div>
<script src="/common.js"></script> <-- remove this
</body>
First copy the default html to your src:
cp .cache/default-html.js src/html.js
Then, edit this line:
/* src/html.js */
<body {...this.props.bodyAttributes}>
{this.props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: this.props.body }}
/>
- {this.props.postBodyComponents}
+ {process.env.NODE_ENV !== 'production' && this.props.postBodyComponents}
</body>
This ensures you can still make use of gatsby's hot reload in development, but generated htmls will not include React & webpack generated scripts.
A more meticulous approach would be to loop over postBodyComponents & only removes the script tag that link to common.js, but for most case I think it'll be fine.
This definitely defeats the purpose of Gatsby, which has its own convention & complex process just so it can generate a progressive web app. For your case, if you're not already familiar with Gatsby, maybe it'd be simpler to roll your own SSR. My answer is only to show whether it's possible with Gatsby or not.

Related

Gatsby - srr or browser to inject html (which is really vue) after webpack babel

I am using snipcart which looks at the static html document and looks for #snipcart element. You can put vue elements in there and the magic will be done on the snipcart.js side.
When using Gatsby, in order to edit the index.html file, you have to create a React file called html.js. In this file I can successfully add Snipcart and everything works. That is until I want to customize the cart and Snipcart uses vue for that. You have to add the vue items in between the #snipcart div.
snipcart-docs-customization
An example
<div hidden id="snipcart" data-api-key="<API_KEY>">
<component-to-override>
<div class="root">
{{ vue_variable.itemText }}
</div>
</component-to-override>
</div>
The problem is, webpack will throw an error if I add vue. This makes sense. So Gatsby has a couple of nice middleware type API's gatsby-ssr and gatsby-browser that might help this.
Looking at these API's I am still unsure how to do this. I need this code added to the index.html as Gatsby is rendering the static pages, at least I feel that is best.
Because Snipcart looks in the #snipcart divs innerHTML for vue formatted components, this is difficult because webpack wants to convert the vue, I do not want it converted.
How can I go about this?
Some useful links I have entertained:
Gatsby Lifecyle
Gatsby-ssr api
Gatsby-browser api
Snipcart customizing components

Fastest way to add pre-existing static HTML page to a React/Gatsby site

I have a simple project working nicely using JSX / React / Gatsby.
I have a pre-existing page (think landing page) in HTML in another project, quite complex, nicely styled using Bootstrap 4, let's call it LandingPage.html and an associated LandingPage.css.
I would like to add the landing page to my Gatsby site. So that for example when navigating to localhost:3000/LandingPage.html the landing page gets shown, properly styled etc.
I am not clear whether I have to fully convert my pre-existing HTML into a react component / JSX?
Or whether I can just serve the LandingPage.html (and associated styling files) by placing it somewhere sensible in my Gatsby project structure?
Or whether I have to create a react "wrapper" that at "run time" reads in the content of LandingPage.html and LandingPage.css?
Note: I've tried just putting the LandingPage.html and LandingPage.css into the /public folder and actually that does work! So maybe I've answered my own question. But is the the right way to do it?
As of Gatsby v2 (don't know about previous versions), it is maybe more consistent to add the file to the /static folder.
According to the docs, the /public folder is meant to be generated automatically when building the site and should be added to .gitignore.
Files added to the /static folder will be copied to /public when building the site so it should have the same effect. More info here.

External Hosted React JS with plain Javascript and HTML page

We have a common widget in each of our pages across multiple services, and we want to write a common client-side rendition code in ReactJS for this widget as an external hosted js, such that each of the pages can include this externally hosted JS in their pages to render the widget. But many of these pages are written in different JS frameworks (angular/inferno/typescript/etc) or even in plain vanilla JS. Now pardon me if this is an ignorant question, but I think that ReactJS code can be compiled into javascript using babel, and the bundled js file can then be directly included in any page using any framework(angular/typescript/etc). Is my assumption correct, or will such an approach lead to problems. Any other inputs?
PS: I am very new to any of these JS frameworks, and have only worked on small projects involving plain vanilla JS.
You can mount your react root node (typically <App/> ) in any html DOM node. This is what react-dom does by
render( <App />, document.getElementById("root"));
which would be a familiar line for you.
Now, coming to how to actually do this. I assume you are using create-react-app.
Run npm run build inside your project folder.
When it finishes, you will find a bunch of files inside your-project-folder/build, including
build/index.html
build/static/js, build/static/css, etc
Open the build/index.html file in a text editor and study it. I think you will be able to figure out the rest.

React index.html page separation using webpack

I am using react's create-react-app for my new application.
I am really getting confused to separate index.html page for client side and admin panel.
I have different functional flows and css files for both side.
So index.html file should be loaded based on router navigation.
Example:
http://example.com => should load client/index.html
http://example.com/admin => should load admin/index.html
Note: i have tried webpack's multiple entries method and webpack html plugin. But it only separates bundle files not html(while navigate).
Please help me out.
webpack just a module bundler, It doesn't control which page show, This should be done by router.
if it's single page, you can use react-router
if it's multi page, you can use express route
after using the below code to include the external scripts, I don't really want any additional html pages.
var $script = require("scriptjs")
$script("/myscript.js")

How to use React for individual site components

Given the following scenario, how can I use React/Preact components in my project:
The main/header content is generated using Django (or static html) templates
I want to use React to generate the sidebar and footer components, depending on the page it is sitting on.
I think the following would work, but I don't know how to split or load the bundles according along the following lines:
Load React/React-dom bundle on every page
Load page specific bundles on demand, where needed
How can I bundle single components up using webpack for use in static html pages and display them where needed? How do I configure webpack for that?
Essentially you transpile React from a bunch of JS/JSX files into one JS script (using Babel), which is then loaded in your html document. So it'd be something like this:
<html>
<head>
// Usual head section stuff
</head>
<body>
<div id="header">
This is the Django site header
</div>
<div id="sidebar_root" />
<div>
Blah blah all the site's body content from Django
</div>
<div id="footer_root" />
<script src="react_sidebar.js" />
<script src="react_footer.js" />
</body>
</html>
And you'd have you React components (which would have a bunch of sub-components), one of which is rendered into "react_sidebar.js" and the other into "react_footer.js". So those components would be in React and the others would be Django.
So in order to load React bundle scripts on demand, you just need to include the script and the div which acts as its root.
P.S.
If you were always loading the sidebar and footer together (i.e. never just one or the other bur always both) you could combine them React DOM rendering into one script, so you'd only have to include one script in your html

Resources