Javascript 在ES6中导入用于服务器端渲染的组件
我有一个很好的小ES6React组件文件(为了这个解释简化了)。它使用特定于浏览器的库,所有这些都在浏览器上运行良好:Javascript 在ES6中导入用于服务器端渲染的组件,javascript,node.js,reactjs,ecmascript-6,Javascript,Node.js,Reactjs,Ecmascript 6,我有一个很好的小ES6React组件文件(为了这个解释简化了)。它使用特定于浏览器的库,所有这些都在浏览器上运行良好: /app/components/HelloWorld.js: 从“React”导入React,{Component}; 从“存储”导入存储; 导出默认类HelloWorld扩展组件{ componentDidMount(){ store.set('my-local-data','foo-bar-baz'); } render(){ 返回( 你好,世界 ); } } 现在,我尝
/app/components/HelloWorld.js:
从“React”导入React,{Component};
从“存储”导入存储;
导出默认类HelloWorld扩展组件{
componentDidMount(){
store.set('my-local-data','foo-bar-baz');
}
render(){
返回(
你好,世界
);
}
}
现在,我尝试使用以下方法在服务器上渲染它:
/server/routes/hello-world.js:
从“React”导入React;
从“react dom/server”导入ReactDOMServer;
从“../../app/components/HelloWorld”导入HelloWorld
导出默认功能(req、res){
res.render('根'{
reactHTML:ReactDOMServer.renderToString(),
});
}
由于导入“存储”,我从节点服务器收到一个错误,提示“未定义窗口”。理想情况下,我可以通过检测环境(节点与浏览器)有条件地导入,但ES6不支持有条件导入
最好的办法是什么?我实际上不需要执行浏览器代码(在这种情况下,componentDidMount
不会被ReactDOMServer.renderToString
调用),只需从节点运行它即可。一种方法是使用。您可以通过插件
选项将其添加到babel寄存器
require('babel/register')({
plugins: ['babel-rewire-plugin']
});
然后将存储
依赖项重新连接到模拟存储:
HelloWorld.__Rewire__('store', {
set: () => {} // no-op
});
您现在可以从服务器和平地呈现HelloWorld。如果您想抑制某些npm模块的加载,您可以对其进行模拟 在导入
HelloWorld.js
之前,将其放在node.js应用程序设置中:
require.cache[require.resolve('store')] = {
exports: {
set() {} // no-op
}
};
将使用此值代替实际模块,实际模块不需要用于您的目的。Node.js模块API是稳定的,因此这种行为不会被破坏,您可以依赖它。您正在做的事情将导致很多问题。据我所知,store.js是一个将数据保存到本地存储的库。根据设计,localStorage是一种浏览器功能,因此您无法从服务器访问用户的localStorage。如果组件的服务器端呈现依赖于
存储
,您应该检查您的体系结构。不,请参阅我的最后一行,关于不想调用此代码而只让它编译。ReactDOMServer永远不会执行存储逻辑,因为它只调用render()
ok,明白了。看看我的答案。