web-dev-qa-db-fra.com

Définir les éléments de stockage local avant le chargement de la page dans le marionnettiste?

Nous avons une logique de routage qui vous renvoie à la page d'accueil si vous n'avez pas de jeu JWT_TOKEN ... Je veux le régler avant que la page ne se charge/avant que le js soit invoqué.

comment puis-je faire cela ?

12
christoffee

Vous devez enregistrer localStorage élément comme ceci:

await page.evaluate(() => {
  localStorage.setItem('token', 'example-token');
});

Vous devriez le faire après la page page.goto - le navigateur doit avoir une URL pour y enregistrer un élément de stockage local. Après cela, entrez à nouveau la même page, cette fois le jeton devrait être ici avant que la page ne soit chargée.

Voici un exemple pleinement fonctionnel:

const puppeteer = require('puppeteer');
const http = require('http');

const html = `
<html>
  <body>
    <div id="element"></div>

    <script>
      document.getElementById('element').innerHTML = 
        localStorage.getItem('token') ? 'signed' : 'not signed';
    </script>
  </body>
</html>`;

http
  .createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write(html);
    res.end();
  })
  .listen(8080);

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('http://localhost:8080/');

  await page.evaluate(() => {
    localStorage.setItem('token', 'example-token');
  });

  await page.goto('http://localhost:8080/');

  const text = await page.evaluate(
    () => document.querySelector('#element').textContent
  );

  console.log(text);
  await browser.close();

  process.exit(0);
})();
15
Everettss

Il y a une discussion à ce sujet dans Problèmes GitHub de Puppeteer .

Vous pouvez charger une page sur le domaine, définir votre localStorage, puis aller à la page réelle que vous souhaitez charger avec localStorage prêt. Vous pouvez également intercepter le premier chargement d'URL pour revenir instantanément au lieu de charger réellement la page, ce qui vous fera potentiellement gagner beaucoup de temps.

const doSomePuppeteerThings = async () => {
  const url = 'http://example.com/';
  const browser = await puppeteer.launch();
  const localStorage = { storageKey: 'storageValue' };
  setDomainLocalStorage(browser, url, localStorage);

  const page = await browser.newPage();
  // do your actual puppeteer things now
};

const setDomainLocalStorage = async (browser, url, values) => {
  const page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('request', r => {
    r.respond({
      status: 200,
      contentType: 'text/plain',
      body: 'Tweak me.',
    });
  });
  await page.goto(url);
  await page.evaluate(values => {
    for (const key in values) {
      localStorage.setItem(key, values[key]);
    }
  }, values);
  await page.close();
};
3
markdon

Sans exiger de doubler goTo, cela fonctionnerait:

const browser = await puppeteer.launch();
browser.on('targetchanged', async (target) => {
  const targetPage = await target.page();
  const client = await targetPage.target().createCDPSession();
  await client.send('Runtime.evaluate', {
    expression: `localStorage.setItem('hello', 'world')`,
  });
});
// newPage, goTo, etc...

Adapté de la doc du phare pour les marionnettistes qui font quelque chose de similaire: https://github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md

0
Rémi Gebski