#node.js #puppeteer #google-chrome-headless #serverside-javascript
#node.js #puppeteer #google-chrome-безголовый #серверная часть-javascript
Вопрос:
Я пытаюсь настроить рендеринг на стороне сервера для внешних страниц Javascript. Я использую Puppeteer для этой цели, и когда я предоставляю любой внешний URL (не страницы локального хостинга), Puppeteer извлекает только исходный код URL-адреса (то, что вы можете увидеть в режиме просмотра исходного кода запрашиваемой страницы), без отображения всего DOM. Когда я пытаюсь SSR любой URL-адрес страницы localhost Javascript (страница, сгенерированная тем же узловым js-сервером на моем локальном хосте) — все работает нормально.
Пожалуйста, сообщите, не упускаю ли я чего-либо или мне нужно попробовать другой подход.
Мне удалось настроить puppeteer со всеми зависимостями от моего локального хостинга, как показано ниже:
В настоящее время переменная ‘html’ возвращает только исходный код выбранного URL-адреса, мне нужно получить полностью отображенный DOM запрошенного URL-адреса.
Код в server.js
var puppeteer = require('puppeteer');
async function ssr(url) {
console.info('rendering the page in ssr mode');
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
try {
await page.goto(url, {waitUntil: 'domcontentloaded'});
} catch (err) {
console.error(err);
throw new Error('page.goto/waitForSelector timed out.');
}
const html = await page.content();
await browser.close();
return {html};
}
module.exports = ssr;
Код в app.js
var err = require('http-errors');
var express = require('express');
var path = require('path');
var ssr = require('./ssr.js');
var app = express();
app.listen(3000, function(){ console.info('Server listening on port '); });
app.use('/index/', async(req, res) => {
const { html } = await ssr(`www.example.com`);
return res.send(html);
});
Ответ №1:
Проблема, вероятно, в том, что вы не даете странице достаточно времени для отображения содержимого DOM. {waitUntil: 'domcontentloaded'}
будет ожидать только события DOMContentLoaded, а не каких-либо AJAX-запросов или модификаций DOM.
Попробуйте вместо этого использовать 'networkidle0'
or 'load'
в качестве waitUntil
значения функции page.goto.goto.goto.
Если это не сработает, у вас есть два варианта:
- Дайте странице фиксированное количество времени для отображения страницы с помощью
await page.waitFor(1000)
- Используйте
await page.waitForSelector(/* ... */)
, чтобы дождаться загрузки определенного селектора перед вызовомpage.content()
. Таким образом, вы можете убедиться, что интересующие вас части документа загружены.
Комментарии:
1. На самом деле я пытался использовать параметры, описанные в официальной документации Google: ‘networkidle0’, ‘networkidle2’ и page.waitForSelector (…) перед публикацией моего публичного вопроса, но результат был тот же — Puppeteer вернул только исходный HTML-код URL-адреса (как если бы я проверил страницу в режиме просмотра исходного кода). Все это идеально работает только для страниц, которые генерируются NodeJS на локальном хостинге. Даже не знаю, что проверять.
2. Привет, Томас! К сожалению, это не так… Может ли это быть из-за localhost (но, я думаю, для этого нет причин). Люди с форума разработчиков Chrome не отвечают. Нет, идея…
3. Я получаю 404 отчета в терминале для всех связанных скриптов и изображений…
Ответ №2:
попробуйте
const html = 'what ever you selector is but since you want the html just type in "html"';
let gg = await page.evaluate((sel) => {
let element = document.querySelector(sel);
console.log ('got Boom');
return element? element.innerHTML: null;
}, html);
console.log (gg);
Комментарии:
1. Привет, Раках Хабаб!
2. Спасибо за ваш ответ! Я пока не эксперт, поэтому не могли бы вы, пожалуйста, уточнить, куда именно мне следует интегрировать предоставленный вами фрагмент кода?
3. Внутри вашего оператора try
4. Спасибо, Рак. Я попробовал — снова в терминал возвращается только исходный код запрошенной страницы, сборка DOM с помощью JS не отображается. Не знаю, что тогда делать…
5. Я не знаю, какой результат вы хотите. Например, вы хотите, чтобы текст заголовка в данном случае был «Example» ИЛИ вы хотите, чтобы он был таким «<h> Example<h>»