使用nginx上的create-react-app的prerender.io不提供项目根目录中的静态文件,而是预渲染root。反应快照也不起作用

时间:2018-01-31 09:40:51

标签: reactjs nginx create-react-app prerender

我根据https://prerender.io/documentation使用create-react-app完成了nginx的大部分必要设置,但我确实有几个问题

但是让我解释一下我的项目设置。

我的文件夹结构

公共   /index.html SRC /   组件   集装箱
  index.js(容器应用)

src / index.js 看起来像

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
);

在我的nginx中,我已将根指定为/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`.
-->

方法#1 - Nginx工作正常并在此页面上显示html。 默认情况下,捆绑包不存在。显然,当我们启动纱线开始或npm开始时,webpack处理这个部分。如何将此bundle.js添加到index.html,以便prerender.io服务可以找到它并返回生成的反应页面的html?或者我甚至需要这样做?

方法#2 - 我在端口上启动项目说3001(纱线启动)然后在我的预渲染服务器开启的情况下,我运行了http://localhost:3000/http://localhost:3001

其中http://localhost:3000 = Prerender.io服务器 http://localhost:3001是项目运行的地方。

现在,

  1. 它不会从项目根目录http://localhost:3001提供我的静态资产,而是来自http://localhost:3000

  2. 其次,在这种情况下,我不觉得有必要手动设置nginx。我需要的只是prerender服务器,我的项目已经通过yarn start运行。

  3. 我觉得第2点适用于本地测试。第1点将适用于预渲染的实际部署。

  4. 方法#3 - create-react-app本身具有预渲染的反应快照,但在我的设置中也会出现错误

    index.js文件

    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
    );
    

    运行时会出现错误Syntax error: Unexpected token, expected , (15:14)

    对于方法#1和#2,思维是否正确?最简单的方法#3有什么问题?

    更新 - nginx.conf文件

    #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/*;
    }
    

    更新2 -

    我尝试访问http://localhost:8000/localhost:3001其中 http://localhost:8000是我的nginx服务器。

    但它只给我页眉和页脚。尝试添加<script> window.prerenderReady = false; </script>。但它部分呈现。

1 个答案:

答案 0 :(得分:0)

方法#2对于在本地测试事物是正确的。由于您直接在浏览器中访问Prerender服务器,因此预计会查看http://localhost:3000请求的静态资产。一旦你正确设置了nginx配置,你就会通过nginx提供预渲染的页面,这些问题就会消失。

方法#1应该在生产中工作,因为bundle文件将包含在index.html中,但是在本地你需要让你的nginx只对你的localhost webpack服务器执行proxy_pass。这样你就可以从npm start获得注入的包。