I have done most of the necessary setup of nginx with create-react-app according to https://prerender.io/documentation but I do have a few questions
But let me explain my project setup.
My folder structure
public
/index.html
src/
components
containers
index.js(Container app)
src/index.js looks like
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {ConnectedRouter} from 'react-router-redux';
import './index.css';
import './main.css';
import App from './containers/app';
import store, { history } from './store';
const target = document.querySelector('#root');
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
target
);
In my nginx I have specified the root as /path/to/project/public/index.html
Index.html
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">
My custom text
</div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
Approach #1 - Nginx works fine and shows up the html on this page. The bundle is not there by default. Obviously, the webpack handles this part when we spin up yarn start or npm start. How can I add this bundle.js to index.html so that prerender.io service would find it and returns back generated html for the react page ? Or do I even need to do this way ?
Approach #2 - I started up project on port say 3001(yarn start) and then with my prerender server ON, I ran http://localhost:3000/http://localhost:3001
where http://localhost:3000 = Prerender.io server and http://localhost:3001 is where my project runs.
Now,
It doesn't serves my static assets from project root i.e. http://localhost:3001 but rather from http://localhost:3000
Second, in this case, I don't feel the need if nginx setup by me manually. All I needed was prerender server and my project already r running via
yarn start.I feel point 2 works for local testing. point 1 will be applicable to actual deployment of pre-rendering.
Approach #3 - create-react-app itself has react-snapshot for pre-rendering, but it gives an error as well in my setup
index.js file
import React from 'react';
// import ReactDOM from 'react-dom';
import { render } from 'react-snapshot';
import {Provider} from 'react-redux';
import {ConnectedRouter} from 'react-router-redux';
import './index.css';
import './main.css';
import App from './containers/app';
import store, { history } from './store';
const target = document.querySelector('#root');
render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
target
);
On running it gives error Syntax error: Unexpected token, expected , (15:14)
Is the thinking correct for approach #1 and #2. And what is the problem with simplest approach #3?
Update - nginx.conf file
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 8000;
server_name localhost;
root /Users/vedant/Projects/myProject/build;
index index.html;
location / {
try_files $uri @prerender;
}
location @prerender {
proxy_set_header X-Prerender-Token eNlgaUedb3xptcXiFlex;
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {
set $prerender 0;
}
#resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
resolver 8.8.8.8;
if ($prerender = 1) {
#setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
set $prerender "service.prerender.io";
rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://$prerender;
}
if ($prerender = 0) {
rewrite .* /index.html break;
}
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
include servers/*;
}
Update 2 -
I tried accessing http://localhost:8000/localhost:3001 where http://localhost:8000 is my nginx server.
But it gives me header and footer only. Tried adding <script> window.prerenderReady = false; </script> as well. But it is partially rendered.