Headless Chrome & Cloudinary for progressively enhanced dynamic content

A presentation at JAMstack_conf San Francisco in October 2019 in San Francisco, CA, USA by Ire Aderinokun

Slide 1

Slide 1

Headless Chrome & Cloudinary for progressively enhanced dynamic content on the web Ire_Aderinokun JAMstack_conf_sf 2019

Slide 2

Slide 2

73% of websites in 2006 were reliant on Javascript for their core functionality

Slide 3

Slide 3

😕 Performance 😕 Accessibility 😕 Progressive Enhancement

Slide 4

Slide 4

We can use Javascript and the JAMstack to improve Javascript

Slide 5

Slide 5

💻 Frontend Developer & Cofounder, BuyCoins # Lagos, Nigeria Google Web Expert & Cloudinary Media Expert Writer, bitsofco.de

Slide 6

Slide 6

Slide 7

Slide 7

<p class=”ciu_embed” data-feature=”flexbox” data-periods=”future_1,current,past_1”> <a href=“http://caniuse.com/#feat=flexbox“> Can I Use flexbox? </a> Data on support for the flexbox feature across the major browsers from caniuse.com. </p>

Slide 8

Slide 8

😕

Slide 9

Slide 9

😕 Javascript disabled 😕 Slow connections 😕 Emails, READMEs, etc

Slide 10

Slide 10

🤔

Slide 11

Slide 11

💡

Slide 12

Slide 12

Slide 13

Slide 13

😕 😊

Slide 14

Slide 14

const puppeteer = require(‘puppeteer’); const browser = await puppeteer.launch({ defaultViewport: { width: 800, height: 800, isLandscape: true } }); const page = await browser.newPage(); await page.goto( embedUrl, { waitUntil: ‘networkidle2’ } ); const screenshot = await page.screenshot({ omitBackground: true, encoding: ‘binary’ }); await browser.close();

Slide 15

Slide 15

const puppeteer = require(‘puppeteer’); const browser = await puppeteer.launch({ defaultViewport: { width: 800, height: 800, isLandscape: true } }); const page = await browser.newPage(); await page.goto( embedUrl, { waitUntil: ‘networkidle2’ } ); const screenshot = await page.screenshot({ omitBackground: true, encoding: ‘binary’ }); await browser.close();

Slide 16

Slide 16

const puppeteer = require(‘puppeteer’); const browser = await puppeteer.launch({ defaultViewport: { width: 800, height: 800, isLandscape: true } }); const page = await browser.newPage(); await page.goto( embedUrl, { waitUntil: ‘networkidle2’ } ); const screenshot = await page.screenshot({ omitBackground: true, encoding: ‘binary’ }); await browser.close();

Slide 17

Slide 17

const puppeteer = require(‘puppeteer’); const browser = await puppeteer.launch({ defaultViewport: { width: 800, height: 800, isLandscape: true } }); const page = await browser.newPage(); await page.goto( embedUrl, { waitUntil: ‘networkidle2’ } ); const screenshot = await page.screenshot({ omitBackground: true, encoding: ‘binary’ }); await browser.close();

Slide 18

Slide 18

const cloudinary = require(‘cloudinary’).v2; cloudinary.config(/*” config here */$); cloudinary.uploader.upload_stream((error, result) =>& { if (error) reject(error) return result.secure_url; }).end(screenshot);

Slide 19

Slide 19

const cloudinary = require(‘cloudinary’).v2; cloudinary.config(/*” config here */$); cloudinary.uploader.upload_stream((error, result) =>& { if (error) reject(error) return result.secure_url; }).end(screenshot);

Slide 20

Slide 20

const cloudinary = require(‘cloudinary’).v2; cloudinary.config(/*” config here */$); cloudinary.uploader.upload_stream((error, result) =>& { if (error) reject(error) return result.secure_url; }).end(screenshot);

Slide 21

Slide 21

const cloudinary = require(‘cloudinary’).v2; cloudinary.config(/*” config here */$); cloudinary.uploader.upload_stream((error, result) =>& { if (error) reject(error) return result.secure_url; }).end(screenshot);

Slide 22

Slide 22

<p class=”ciu_embed” data-feature=”flexbox” data-periods=”future_1,current,past_1”> <a href=“http://caniuse.com/#feat=flexbox“> Can I Use flexbox? </a> Data on support for the flexbox feature across the major browsers from caniuse.com. </p> 😕

Slide 23

Slide 23

<p class=”ciu_embed” data-feature=”flexbox” data-periods=“future_1,current,past_1”> <a href=“http://caniuse.com/#feat=flexbox“> <img src=“https://res.cloudinary.com/ireaderinokun/image/upload/v1571256076/ caniuse-embed/flexbox-2019-10-16.png” alt=”Data on support for the flexbox feature across the m…”> </a> </p> 😊

Slide 24

Slide 24

<p class=”ciu_embed” data-feature=”flexbox” data-periods=“future_1,current,past_1”> <a href=“http://caniuse.com/#feat=flexbox“> <picture> <source type=”image/webp” srcset=”https://res.cloudinary.com/ ireaderinokun/image/upload/v1571256076/caniuse-embed/flexbox-2019-10-16.webp”> <source type=”image/png” srcset=”https://res.cloudinary.com/ ireaderinokun/image/upload/v1571256076/caniuse-embed/flexbox-2019-10-16.png”> <source type=”image/jpeg” srcset=”https://res.cloudinary.com/ ireaderinokun/image/upload/v1571256076/caniuse-embed/flexbox-2019-10-16.jpg”> <img src=”https://res.cloudinary.com/ireaderinokun/image/upload/ v1571256076/caniuse-embed/flexbox-2019-10-16.png” alt=”Data on support for the flexbox feature across the major browsers from caniuse.com”> </picture> </a> </p> 🤩

Slide 25

Slide 25

Slide 26

Slide 26

JAMstackifying

Slide 27

Slide 27

Slide 28

Slide 28

JAMstackifying

Slide 29

Slide 29

exports.handler = async (event, context) =>& { const const const const params = JSON.parse(event.body); feature = params.feature; periods = params.periods; a11yColours = params.a11yColours; try { const screenshot = await takeScreenshot(feature, periods, a11yColours); const image = await uploadScreenshot(feature, screenshot); return { statusCode: 200, body: JSON.stringify(image) }; } catch (err) { return { statusCode: 500, body: err.toString() } } };

Slide 30

Slide 30

Thank you! 🌐 Where to find me 📚 Further reading & sources • ireaderinokun.com • http://news.bbc.co.uk/2/hi/technology/ 6210068.stm • bitsofco.de • • @ireaderinokun https://bitsofco.de/using-a-headlessbrowser-to-capture-page-screenshots/ • https://bitsofco.de/how-to-upload-ascreenshot-from-puppeteer-tocloudinary/ ⭐ Use the embed • caniuse.bitsofco.de