【问题标题】:Rendering React.js clientside webapp with PhantomJS使用 PhantomJS 渲染 React.js 客户端 Web 应用程序
【发布时间】:2016-12-20 04:00:38
【问题描述】:

一位朋友让我捕获一个使用 React.js 构建的客户端渲染网站,最好使用 PhantomJS。我正在使用一个简单的渲染脚本如下:

var system = require('system'),
fs = require('fs'),
page = new WebPage(),
url = system.args[1],
output = system.args[2],
result;

page.open(url, function (status) {
if (status !== 'success') {
  console.log('FAILED to load the url');
  phantom.exit();
} else {
  result = page.evaluate(function(){
      var html, doc;

      html = document.querySelector('html');

      return html.outerHTML;
  });

  if(output){

    var rendered = fs.open(output,'w');
    rendered.write(result);
    rendered.flush();
    rendered.close();

  }else{

    console.log(result);

  }
}
phantom.exit();
});

网址是http://azertyjobs.tk

我总是出错

ReferenceError: Can't find variable: Promise

http://azertyjobs.tk/build/bundle.js:34
http://azertyjobs.tk/build/bundle.js:1 in t
...

好的,所以我发现 PhantomJS 本身并不支持 ES6 Promises,所以我尝试了各种额外的包,如以下 https://www.npmjs.com/package/es6-promise 并启动了变量:

var Promise = require('es6-promise').Promise

然而,这仍然会产生同样的错误,尽管 Promise 现在是一个函数。网页的输出也还是空的(显然..)

现在我很老派了,所以整个客户端渲染的东西有点超出我的想象(在各个方面),但也许有人有解决方案。我也尝试过使用等待脚本,但这绝对没有带来任何好处。我会完全错了吗?这甚至可以做到吗?

非常感谢!

路德维希

【问题讨论】:

  • PhantomJS 有自己糟糕的 Javascript 实现,而不是使用像 Node.如果你想将 Phantom 与其他 Node 库一起使用,则必须使用糟糕的集成软件,例如 github.com/amir20/phantomjs-node
  • @AndyRay 有道理。您可能应该将 Node 与 Nightmare 之类的东西一起使用。
  • 好吧,伙计们,会检查一下!谢谢

标签: javascript reactjs promise phantomjs server-side-rendering


【解决方案1】:

我尝试了您链接的 polyfill,但它不起作用,更改为 core.js 并且能够制作屏幕截图。您需要在页面打开之前注入 polyfill:

page.onInitialized = function() {
    if(page.injectJs('core.js')){
        console.log("Polyfill loaded");
    }    
}

page.open(url, function (status) {

    setTimeout(function(){
        page.render('output.jpg');
        phantom.exit();
    }, 3000);

});

【讨论】:

  • 好吧,这听起来很有希望。谢谢!我已经使用npm i core-js 安装了 core.js(请原谅我在这里的菜鸟)我如何实际访问它?
  • 指明您计算机上 core.js 文件的路径:page.injectJs('local/path/to/file/core.js')。最简单的方法是将其移动到 PhantomJS 脚本所在的目录。
  • 很累,忽略了 core-js 包的/client/ 目录。无论如何,这似乎有效!非常感谢。
【解决方案2】:

您需要了解的是,页面加载有几个部分。首先是 HTML - 与您在网页上“查看源代码”时看到的内容相同。接下来是加载的图像和脚本以及其他资源。然后执行脚本,这可能会也可能不会导致加载更多内容以及对 HTML 进行可能的修改。

然后你必须做的是找出一种方法来确定用户看到页面的实际“加载”时间。 PhantomJS 提供了一个范式供你以waitFor 加载内容。通读他们的例子,看看你是否能找到适合你的方法。请特别注意他们将phantom.exit(); 放在哪里,因为您想确保在最后发生这种情况。祝你好运。

【讨论】:

  • 虽然在很多情况下都是如此,但对于 React 应用程序还有很多其他问题。对我来说,它没有在我的 webpack 配置中包含 es2015,因此它没有正确地将类编译为浏览器友好的代码。
【解决方案3】:

您尝试在哪里(如何)初始化Promise?您需要将其创建为 window 的属性,或者使用 es6-promise 作为全局 polyfill,例如 require('es6-promise').polyfill();require('es6-promise/auto');(来自 readme)。

另外,“捕获”是什么意思?如果您尝试抓取数据,使用X-ray 可能会更好。它支持 Phantom、Nightmare 和其他驱动程序。

请记住,React 也可以是服务器渲染的。 React 类似于模板,但具有实时数据绑定。它并不像你想象的那么复杂。

【讨论】:

  • 感谢您的回答。我实际上尝试了require('es6-promise').polyfill(); 并将 Promise 设置为window 的属性,但都没有奏效。是的,我的意思是抓取数据,感谢您的建议,我会检查一下。我知道这一点,但这超出了我的控制范围:)
猜你喜欢
  • 2014-03-20
  • 2016-08-10
  • 2017-07-13
  • 2015-07-12
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
相关资源
最近更新 更多