Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Emails and PDFs with React

Building Emails and PDFs with React

Did you ever need to generate PDFs or e-mails? Was it fun? I guess not. Maybe the solution is in the tools you are already using. Taking advantage of React server-side rendering you can make the process less painful and the code easier to maintain.

We will be discussing the complexities of building emails and PDFs as well as going through two real case studies to explain how we managed to ship these functionalities.

TLDR; React components benefits can be used outside a typical web application. "Good enough" is fine. Ship it!

OUTLINE:

Emails:
- Problems: text-only emails, consistency, tables.
- Idea: SSR with the benefits of components
- Case study: Séntisis emails
- Using components to remove complexities
- Demo repo and how to use it
- Behind the scenes

PDFs:
- Problems: complexity, styling
- Initial idea: SSR using components + wkhtmltopdf
- Case study: Séntisis reports
- Demo repo and how to use it
- Doing it better: using a headless browser
- Conclusion and with an ending "Dancing Hopper" GIF

Fernando Agüero

November 22, 2017
Tweet

More Decks by Fernando Agüero

Other Decks in Programming

Transcript

  1. Hello!
    I’m
    Fernando Agüero.

    View full-size slide

  2. Madrid
    Devs
    I help
    these
    communities
    ValenciaJS

    View full-size slide

  3. Building
    Emails & PDFs
    with React

    View full-size slide

  4. bit.ly/react-emails-pdf

    View full-size slide

  5. Building
    Emails
    with React

    View full-size slide

  6. Emails are hard

    View full-size slide

  7. Image from the Campaign Monitor Engineering Blog

    View full-size slide

  8. You can always use
    Multi-part MIME
    FYI
    More accessible and less spammy!

    View full-size slide

  9. Multi-part_MIME
    Multi-part mime refers to sending
    both an HTML and TEXT part of
    an email message in a single email

    View full-size slide

  10. Multi-part_MIME
    Plain text
    HTML

    View full-size slide

  11. September_2016
    Google adds support for:
    • media queries
    • embedded stylesheets
    • class and ID support

    View full-size slide

  12. Is not that bad now

    View full-size slide

  13. Example of an email before and after responsive design

    View full-size slide

  14. HTML emails
    are here to stay,
    and you will need to
    build them.

    View full-size slide

  15. Case study:
    Séntisis Emails

    View full-size slide

  16. What is behind:

    View full-size slide

  17. A typical email with nested tables madness

    View full-size slide

  18. Modularization
    Logo from the react-icons package
    and React

    View full-size slide

  19. Components
    We created a component
    to encapsulate the complexities of
    the tables.

    View full-size slide

  20. Actual
    output

    View full-size slide

  21. Components
    The Grid component handles the
    row and the cells to always
    generate a valid HTML table.

    View full-size slide

  22. Components
    Nested tables get complex and can
    lead to non-valid HTML, causing
    email parsers to break the layout.

    View full-size slide

  23. Empty element
    WTF?

    View full-size slide

  24. Components
    The Grid component can be used as
    a wrapper or by using its Cell and
    Row components.

    View full-size slide

  25. Grid.Cell and Grid.Row components

    View full-size slide

  26. Grid component

    View full-size slide

  27. Components
    Once we are able to stop thinking
    about tables, we can move forward
    and continue creating our emails as
    a typical React application.

    View full-size slide

  28. Build a weather report
    demo email
    How_to

    View full-size slide

  29. github.com/lang-ai/react-emails
    Demo_Repository
    Bootstrapped with create-react-app

    View full-size slide

  30. Usage
    1. npm install
    2. npm run build
    3. node example/weather.js
    4. Enjoy your generated email

    View full-size slide

  31. npm run build
    Transpile our React code with Babel
    to get rid of the JSX and the ES6 imports

    View full-size slide

  32. package.json

    View full-size slide

  33. node example/weather.js
    Generate a forecast email

    View full-size slide

  34. Behind_the_scenes
    Connecting the dots

    View full-size slide

  35. Behind_the_scenes
    1. Fetch weather API for the example
    2. Create a React element with the API data by
    rendering it on the server

    View full-size slide

  36. Behind_the_scenes
    3. Add styles and the React element in a placeholder
    4. Return the generated HTML
    5. Save or send the email

    View full-size slide

  37. example/weather.js

    View full-size slide

  38. example/weather.js
    1. Fetch API data

    View full-size slide

  39. example/weather.js
    2-4. Generate HTML

    View full-size slide

  40. example/weather.js
    5. Send or save the email

    View full-size slide

  41. How it works

    View full-size slide

  42. server/createEmail.js
    Optional CSS
    to be inlined
    Base HTML to add
    our styles and content

    View full-size slide

  43. server/createEmail.js
    Generate our
    email HTML

    View full-size slide

  44. server/createEmail.js
    Add our HTML
    and styles to the
    placeholder

    View full-size slide

  45. server/email-placeholder.html
    This gets replaced to
    have our final HTML

    View full-size slide

  46. Using it for real
    Production

    View full-size slide

  47. Production
    • Used as an npm package
    • Transpiles on the npm install hook

    View full-size slide

  48. Production
    Steps:
    • Create a new layout React component
    • Pass props to that layout
    • Send email

    View full-size slide

  49. Usage example

    View full-size slide

  50. Layouts
    Each email layout is
    a React component

    View full-size slide

  51. Benefits
    1. It’s a React app: same tooling, live reload
    2. Remove complexity with wrappers:
    3. Ability write logic in the templates

    View full-size slide

  52. Building
    PDFs
    with React
    (kind of)

    View full-size slide

  53. Case study:
    Séntisis Reports

    View full-size slide

  54. PDFs are hard

    View full-size slide

  55. PDFs are complex

    View full-size slide

  56. Avoid complexity

    View full-size slide

  57. complexity
    uncertainty
    scope changes

    View full-size slide

  58. Idea
    • Node
    • React + SSR
    • HTML to PDF?

    View full-size slide

  59. • Open Source command line tool
    • Renders HTML into PDF
    • Uses the Qt Webkit rendering engine
    • Headless (does not require a display service)

    View full-size slide

  60. CSS support?

    View full-size slide

  61. It’s not perfect

    View full-size slide

  62. Don’t expect top-notch CSS support

    View full-size slide

  63. It’s not perfect
    but it get’s the job done

    View full-size slide

  64. Evolution chart rendered in the PDF

    View full-size slide

  65. Build an invoice
    demo PDF
    How_to

    View full-size slide

  66. github.com/lang-ai/react-pdfs
    Demo_Repository
    Bootstrapped with create-react-app

    View full-size slide

  67. Usage
    1. npm install
    2. npm run build
    3. node example/invoice.js
    4. Enjoy your generated PDF

    View full-size slide

  68. Behind_the_scenes
    Connecting the dots

    View full-size slide

  69. Behind_the_scenes
    1. Build your components
    2. Render the HTML on the server
    3. Pass the HTML to wkhtmltopdf
    Similar to react-emails

    View full-size slide

  70. Same previous process as with react-emails

    View full-size slide

  71. How it works

    View full-size slide

  72. server/createPDF.js

    View full-size slide

  73. Is there a better way?

    View full-size slide

  74. Headless browsers

    View full-size slide

  75. Headless browsers

    View full-size slide

  76. Q: What is the difference between
    Puppeteer, Selenium / WebDriver,
    and PhantomJS?

    View full-size slide

  77. “Puppeteer only works with Chrome and it uses
    the latest version of Chromium. In non-testing use
    cases, Puppeteer provides a powerful but simple
    API because it’s only targeting one browser”

    View full-size slide

  78. “Puppeteer bundles Chromium to ensure that the
    latest features it uses are guaranteed to be available.”
    package.json

    View full-size slide

  79. Q: Ok, but why Puppeteer?

    View full-size slide

  80. • CSS support
    • Export to PDF directly
    Benefits

    View full-size slide

  81. Consider navigation to be finished when
    there are no network connections for at
    least 500 ms

    View full-size slide

  82. Auth & Cookies

    View full-size slide

  83. Cookies
    We needed permission to get
    that user report data

    View full-size slide

  84. We can now fetch the data
    and render the report for that user

    View full-size slide

  85. Takeaways
    • React components benefits can be used
    outside a typical web application
    • “Good enough” is fine
    • Ship it

    View full-size slide

  86. Takeaways
    • React components benefits can be used
    outside a typical web application
    • “Good enough” is fine
    • Ship it

    View full-size slide

  87. fjaguero fjaguero
    Thanks!
    fjaguero.com
    bit.ly/react-emails-pdf

    View full-size slide