使用 PhantomJS 呈现 React.js 客户端 Web 应用程序
Rendering React.js clientside webapp with PhantomJS
一位朋友让我捕获一个使用 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();
});
我总是收到错误消息
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 现在是一个函数。网页的输出也还是空的(很明显..)
现在我已经很老派了,所以整个客户端渲染的东西有点超出我的范围(在各个方面),但也许有人有解决方案。我也尝试过使用等待脚本,但这绝对没有带来任何好处。我是不是完全错了?这甚至可以做到吗?
非常感谢!
路德维希
您需要了解的是,页面加载有几个部分。首先是 HTML - 与您在网页上 "view source" 时看到的相同。接下来加载图像和脚本以及其他资源。然后执行脚本,这可能会或可能不会导致加载更多内容以及对 HTML 的可能修改。
然后您必须做的是想出一种方法来确定该页面何时真正 "loaded" 如同用户看到的那样。 PhantomJS 为您提供了一个范例来加载 waitFor 内容。通读他们的示例,看看您是否能找出适合您的方法。请特别注意他们把 phantom.exit();
放在哪里,因为你想确保它发生在最后。祝你好运。
您要在哪里(如何)初始化 Promise
?您需要将其创建为 window
的 属性,或者使用 es6-promise 作为全局 polyfill,例如 require('es6-promise').polyfill();
或 require('es6-promise/auto');
(来自 readme).
另外,"capture"是什么意思?如果你正在尝试抓取数据,使用 X-ray 可能会更好。支持Phantom、Nightmare等驱动。
还要记住,React 也可以是服务器渲染的。 React 类似于模板,但具有实时数据绑定。它并不像你想象的那么复杂。
我已经尝试了您链接的 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);
});
一位朋友让我捕获一个使用 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();
});
我总是收到错误消息
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 现在是一个函数。网页的输出也还是空的(很明显..)
现在我已经很老派了,所以整个客户端渲染的东西有点超出我的范围(在各个方面),但也许有人有解决方案。我也尝试过使用等待脚本,但这绝对没有带来任何好处。我是不是完全错了?这甚至可以做到吗?
非常感谢!
路德维希
您需要了解的是,页面加载有几个部分。首先是 HTML - 与您在网页上 "view source" 时看到的相同。接下来加载图像和脚本以及其他资源。然后执行脚本,这可能会或可能不会导致加载更多内容以及对 HTML 的可能修改。
然后您必须做的是想出一种方法来确定该页面何时真正 "loaded" 如同用户看到的那样。 PhantomJS 为您提供了一个范例来加载 waitFor 内容。通读他们的示例,看看您是否能找出适合您的方法。请特别注意他们把 phantom.exit();
放在哪里,因为你想确保它发生在最后。祝你好运。
您要在哪里(如何)初始化 Promise
?您需要将其创建为 window
的 属性,或者使用 es6-promise 作为全局 polyfill,例如 require('es6-promise').polyfill();
或 require('es6-promise/auto');
(来自 readme).
另外,"capture"是什么意思?如果你正在尝试抓取数据,使用 X-ray 可能会更好。支持Phantom、Nightmare等驱动。
还要记住,React 也可以是服务器渲染的。 React 类似于模板,但具有实时数据绑定。它并不像你想象的那么复杂。
我已经尝试了您链接的 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);
});