(ReactJS + 无服务器)静态服务页面与虚拟 DOM 错误

(ReactJS + serverless) static served page vs virtual DOM bug

我们正在使用 https://github.com/elastic-coders/serverless-webpack

渲染服务器端 ReactJS 组件

一切正常,组件 data/markup 已渲染。但是,当我们 运行 serverless webpack serve

时,问题就发生了

我们访问了本地主机 link 并且在一瞬间我们看到了该应用程序,然后它进入了一个白页。

如果我们查看源代码进行更深入的检查,我们会看到所有标记,包括 CSS 和 JS,一切。然而,在 Chrome Inspector 中,我们只能看到应用程序 <div> 而没有其他任何东西。就像一旦我们的应用程序脚本行 运行s,我们用虚拟 DOM.

替换静态内容

那些使用 React 和 serverless 渲染静态页面的人,你是如何克服这个问题的?

查看源代码

Chrome督察

我们的handler.js文件

if (!global._babelPolyfill) {
  require('babel-polyfill');
}

import React from 'react'
import ReactDOMServer from 'react-dom/server'
import Home from './src/components/home/HomePage'
const component = ReactDOMServer.renderToStaticMarkup(<Home />);
const html = `<!DOCTYPE html>
<html lang="en">
<head>
    <title>WikiTags</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="author" content="WikiTags.com">
    <meta name="description" content="We rank what people are talking about.">
    <meta name="revisit-after" content="7 days">
    <link href="https://www.wikitags.com/" rel="canonical" />
    <meta name="twitter:card" content="summary">
    <meta name="twitter:site" content="@wikitags">
    <meta name="twitter:creator" content="@wikitags">
    <meta name="twitter:title" content="WikiTags">
    <meta name="twitter:description" content="We rank what people are talking about.">
    <meta name="twitter:image:src" content="http://admin.wikitags.com/dist/imgs/wikitags-twitter.jpg">
    <meta property="og:locale" content="en_US">
    <meta property="og:type" content="app">
    <meta property="og:site_name" content="WikiTags">
    <meta property="og:title" content="WikiTags | We rank what people are talking about.">
    <meta property="og:image" content="http://admin.wikitags.com/dist/imgs/wikitags-twitter.jpg">
    <meta property="og:url" content="https://www.wikitags.com/">
    <meta property="og:description" content="We rank what people are talking about.">
    <link rel="icon" href="http://admin.wikitags.com/dist/imgs/favicon.ico">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link href="http://admin.wikitags.com/dist/wikitags.css" rel="stylesheet">
</head>
<body>
    <div id="wikitags-app">
        ${component}
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="http://admin.wikitags.com/dist/wikitags.bundle.js"></script>
</body>
</html>`;

export const home = (event, context, cb) => {
  const prom = new Promise((resolve, reject) => {
    resolve('success');
  });

  prom
    .then(r => cb(null, html))
    .catch(e => cb(e));
};

我们的webpack.serverless.config

module.exports = {
    entry: './handler.js',
    target: 'node',
    module: {
        loaders: [{
            test: /\.js$/,
            loaders: ['babel?' + JSON.stringify({
                plugins: [
                    'transform-runtime',
                    'transform-es2015-modules-commonjs'
                ],
                presets: ['es2015', 'react', 'stage-0'],
            })],
            include: __dirname,
            exclude: /node_modules/,
        },
        {
            test: /\.scss$/,
            loaders: ["css-loader", "sass-loader"]
        }]
    }
};

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./app";

const root = document.getElementById("wikitags-app");

ReactDOM.render(<App/>, root);

想法


目前看来,我们仍然可以使用 React 来构建组件,我们从服务器获取数据并将该数据作为 props 向下传递到组件中以设置活动状态、选定状态等。 .. 然后无服务器呈现静态视图。

但是,一旦用户获得该页面。我们不能添加实际的 app.bundle.js 文件,因为这会破坏应用程序,如上所示。但是我们需要做的是在静态页面的底部添加原始Javascript或Jquery来处理任何逻辑。

这看起来是正确的/只移动到这里吗?

我们想通了!我们从 Root 中删除了 <Router> 并返回 <HomePage /> 因为我们不需要单页应用程序路由器,因为我们静态地提供所有视图。

路由器正在破坏应用程序,因为它在静态内容加载完成后尝试重新路由应用程序。

所以不用这个

import React from 'react';
import HomePage from './home/HomePage';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import CatgeoryPage from './category/CatgeoryPage';
import EntityPage from './entity/EntityPage';

export class Root extends React.Component {
    render() {
        return (
            <div>
                <Route exact={ true } path="/" component={ HomePage }/>
                <Route path="/category" component={ CatgeoryPage }/>
                <Route path="/entity" component={ EntityPage }/>
            </div>
        );
    }
}

export default Root;

我们有这个

import React from 'react';
import HomePage from './home/HomePage';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import CatgeoryPage from './category/CategoryPage';
import EntityPage from './entity/EntityPage';

export class Root extends React.Component {
    render() {
        return (
            <HomePage />
        );
    }
}


export default Root;