语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <
Posted
技术标签:
【中文标题】语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <【英文标题】:Syntax Error: Unexpected token < while using renderToString(<RoutingContext ...renderProps />语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 < 【发布时间】:2016-03-08 13:02:14 【问题描述】:我正在尝试使用 React 和 React-router 进行服务器端渲染。到目前为止,它只是来自各种来源的复制粘贴代码。但是当我尝试使用 node.js 运行应用程序时出现语法错误(不是运行时错误)。下面是代码
App.js
'use strict';
require('babel/register');
const express = require('express');
const http = require('http');
const handlebars = require('express-handlebars');
const renderToString = require('react-dom').server;
const match = require('react-router').match;
const RoutingContext = require('react-router').RoutingContext;
const Routes = require('./routes');
const app = express();
var server;
// JSX transpilation
require('node-jsx').install();
// Setting up handlebars
app.engine('.hbs', handlebars(
extname: '.hbs',
layoutsDir: 'views/server',
partialsDir: 'views/server/partials'
));
app.set('view engine', '.hbs');
// Mount Routes
app.use('*', function (req, res)
match(routes: routes, location: req.url, (error, redirectLocation, renderProps) =>
if (error)
res.status(500).send(error.message)
else if (redirectLocation)
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
else if (renderProps)
console.log(renderProps);
var pageData =
serverhtml: renderToString(<RoutingContext ...renderProps />)
;
console.log(pageData);
res.render('base', pageData);
else
res.status(404).send('Not found')
);
);
server = http.createServer(app);
server.listen('3000', () =>
console.log('Express server listening on port ' + 3000);
);
我在运行node --harmony app.js
时遇到的错误是
serverHtml: renderToString(<RoutingContext ...renderProps />)
^
SyntaxError: Unexpected token <
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
我是否需要安装/转换(babelify/jsx)我的代码来处理 JSX 样式标签?但是我在网上的任何教程中都没有发现任何这样的内容。
我关注的资源
-
React-router(Serverside Rendering)
Server Side Rendering by React
【问题讨论】:
是的,您必须将 JSX 转换为标准的 JS 代码。 JSX 不是 ECMAScript 标准。 你是说实时编译这段代码并运行吗?像babel-node
之类的?虽然没有教程提到过这个用于服务器端渲染
您可以使用babel-node
进行开发。对于生产,使用之前的工具编译代码,例如react-tools
。
我已经添加了require('node-jsx
).install()`,但仍然没有效果。我还添加了require(babel/register)
。取自以下链接***.com/questions/31580842/… & ***.com/questions/30626410/server-side-rendering-with-react-react-router-and-express?rq=1
【参考方案1】:
注意 - 此方法已弃用。那里有更好的选择。如前所述,require('node-jsx').install()
不再维护,使用 babel 是前进的理想方式。
所以我通过对上面的代码进行一些更改来解决这个问题
我删除了以下行,因为它不是必需的
require('babel/register');
然后我没有通过 babel 转译 app.js,而是使用 React.createElement() 更改了 JSX 标签,如下所示:
//serverHtml: renderToString(<RoutingContext ...renderProps />)
serverHtml: ReactDOM.renderToString(React.createElement(RoutingContext, renderProps))
完整更新代码如下:
'use strict';
const compression = require('compression');
const express = require('express');
const http = require('http');
const handlebars = require('express-handlebars');
const path = require('path');
const React = require('react');
const ReactDOM = require('react-dom/server'); // Fixed this
const match = require('react-router').match;
const RoutingContext = require('react-router').RoutingContext;
const app = express();
var server;
require('node-jsx').install(); // Not required if you convert the below './routes' file from JSX into js
const Routes = require('./routes');
// Used for Gzipping all the resources
app.use(compression());
// Setting up handlebars
app.engine('.hbs', handlebars(
extname: '.hbs',
layoutsDir: 'views/server',
partialsDir: 'views/server/partials'
));
app.set('view engine', '.hbs');
// Set path to public assets
app.use(express.static(path.join(__dirname, 'public')));
// Mount Routes
app.use('*', function (req, res)
match(routes:Routes, location:req.url, (error, redirectLocation, renderProps) =>
if (error)
res.status(500).send(error.message)
else if (redirectLocation)
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
else if (renderProps)
var pageData =
serverHtml: ReactDOM.renderToString(React.createElement(RoutingContext, renderProps))
;
res.render('base', pageData);
else
res.status(404).send('Not found')
);
);
server = http.createServer(app);
server.listen('3000', () =>
console.log('Express server listening on port ' + 3000);
);
谢谢:)
【讨论】:
【参考方案2】:你正在做的事情不会奏效,因为
require('node-jsx').install();
安装一个 require 钩子来编译之后需要的文件。
正如其他人所推荐的,这个项目已被弃用,现在使用 Babel 是最好的方法。
您必须将您的 jsx 保存在单独的模块中,并从您的主文件中要求它。
这是因为JSX
文件在到达 javascript 解释器之前必须被解析并转换为标准 javascript。在这种特定情况下,它是通过拦截公共 js 运行时提供的require
方法来完成的。
但是,包含require('babel/register')
的文件不能包含 JSX 语法,因为要进行注册,文件必须由 javascript 解释器运行,并且必须首先解析文件。此初步步骤将失败,因为 javascript 解释器无法识别 JSX 标签。
此外,如果您使用的是最新版本的 Babel,您将使用 React preset。
【讨论】:
谢谢。我还是不明白。你是说我必须 babelifyapp.js
?我确实在顶部使用了require('babel/register')
。我正在关注这篇文章 ***.com/questions/30626410/server-side-rendering-with-react-react-router-and-expres
我已经用更多解释更新了答案。如果仍然存在一些混乱,请告诉我。
谢谢。我已经解决了这个问题。我使用 React.createElement(RoutingContext, renderProps)
而不是 JSX 标签。这解决了问题:)以上是关于语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <的主要内容,如果未能解决你的问题,请参考以下文章
onClick 处理程序未向 ReactDOMServer.renderToString 注册
angular 2 等效于 react renderToString
React renderToString() 性能和缓存 React 组件