我有一个很好的小ES6 React组件文件(为此解释简化)。它使用特定于浏览器的库store这一切都在浏览器上运行得很漂亮:
/app/components/HelloWorld.js:
import React, { Component } from 'react';
import store from 'store';
export default class HelloWorld extends Component {
componentDidMount() {
store.set('my-local-data', 'foo-bar-baz');
}
render() {
return (
<div className="hello-world">Hello World</div>
);
}
}
现在,我正在尝试使用babel-register在服务器上进行渲染,如下所示:
/server/routes/hello-world.js:
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import HelloWorld from '../../app/components/HelloWorld'
export default function(req, res) {
res.render('root', {
reactHTML: ReactDOMServer.renderToString(<HelloWorld />),
});
}
由于导入“store”,我从节点服务器收到“未定义窗口”的错误。理想情况下,我可以通过检测环境(节点与浏览器)有条件地导入,但ES6不支持条件导入。
解决这个问题的最佳方法是什么?我实际上并不需要执行浏览器代码(在这种情况下componentDidMount
将不会被ReactDOMServer.renderToString
调用)只是让它从节点运行。
答案 0 :(得分:1)
一种方法是使用babel-rewire-plugin。您可以通过plugins
选项
require('babel/register')({
plugins: ['babel-rewire-plugin']
});
然后将您的store
依赖关系重新连接到模拟商店:
HelloWorld.__Rewire__('store', {
set: () => {} // no-op
});
您现在可以安静地从服务器渲染HelloWorld。
答案 1 :(得分:0)
如果你想抑制某些npm模块的负载,你可以模拟它。
在require.cache[require.resolve('store')] = {
exports: {
set() {} // no-op
}
};
导入:
var mytabs = [{
name: "Marc"
}, {
name: "Josef"
}, {
name: "Luis"
}];
$('#tabs').tabs();
$.each(mytabs, function(indexInArray, myobj) {
$('#tabs').find('li> a').eq(indexInArray).text(myobj.name);
});
将使用此值代替实际模块,而不需要用于您的目的。 Node.js模块API是稳定的,因此不会破坏此行为,您可以依赖它。