(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;
我们正在使用 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;