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!


- 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

- 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

More Decks by Fernando Agüero

Other Decks in Programming


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

  3. I work at

  4. None
  5. None
  6. Madrid Devs I help these communities ValenciaJS

  7. Building Emails & PDFs with React

  8. bit.ly/react-emails-pdf

  9. Building Emails with React

  10. None
  11. Emails are hard

  12. Image from the Campaign Monitor Engineering Blog

  13. None
  14. None
  15. You can always use Multi-part MIME FYI More accessible and

    less spammy!
  16. Multi-part_MIME Multi-part mime refers to sending both an HTML and

    TEXT part of an email message in a single email
  17. Multi-part_MIME Plain text HTML

  18. September_2016 Google adds support for: • media queries • embedded

    stylesheets • class and ID support
  19. Is not that bad now

  20. Example of an email before and after responsive design

  21. but…

  22. HTML emails are here to stay, and you will need

    to build them.
  23. Case study: Séntisis Emails

  24. None
  25. None
  26. What is behind:

  27. A typical email with nested tables madness

  28. None
  29. Tables

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

  31. Components We created a <Grid /> component to encapsulate the

    complexities of the tables.
  32. becomes

  33. None
  34. Actual output

  35. Components The Grid component handles the row and the cells

    to always generate a valid HTML table.
  36. Components Nested tables get complex and can lead to non-valid

    HTML, causing email parsers to break the layout.
  37. Empty <td> element WTF?

  38. Components The Grid component can be used as a wrapper

    or by using its Cell and Row components.
  39. Grid.Cell and Grid.Row components

  40. None
  41. None
  42. Grid component

  43. Components Once we are able to stop thinking about tables,

    we can move forward and continue creating our emails as a typical React application.
  44. None
  45. Build a weather report demo email How_to

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

  47. None
  48. Usage 1. npm install 2. npm run build 3. node

    example/weather.js 4. Enjoy your generated email
  49. npm run build Transpile our React code with Babel to

    get rid of the JSX and the ES6 imports
  50. package.json

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

  52. Behind_the_scenes Connecting the dots

  53. 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
  54. Behind_the_scenes 3. Add styles and the React element in a

    placeholder 4. Return the generated HTML 5. Save or send the email
  55. example/weather.js

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

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

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

  59. How it works

  60. server/createEmail.js Optional CSS to be inlined Base HTML to add

    our styles and content
  61. server/createEmail.js Generate our email HTML

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

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

  64. Using it for real Production

  65. Production • Used as an npm package • Transpiles on

    the npm install hook
  66. Production Steps: • Create a new layout React component •

    Pass props to that layout • Send email
  67. Usage example

  68. Layouts Each email layout is a React component

  69. Benefits 1. It’s a React app: same tooling, live reload

    2. Remove complexity with wrappers: <Grid /> 3. Ability write logic in the templates
  70. Building PDFs with React (kind of)

  71. Case study: Séntisis Reports

  72. PDFs are hard

  73. None
  74. None
  75. None
  76. PDFs are complex

  77. None
  78. Avoid complexity

  79. complexity uncertainty scope changes

  80. Idea • Node • React + SSR • HTML to

  81. None
  82. None
  83. • Open Source command line tool • Renders HTML into

    PDF • Uses the Qt Webkit rendering engine • Headless (does not require a display service)
  84. CSS support?

  85. None
  86. It’s not perfect

  87. Don’t expect top-notch CSS support

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

  89. Evolution chart rendered in the PDF

  90. Build an invoice demo PDF How_to

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

  92. None
  93. Usage 1. npm install 2. npm run build 3. node

    example/invoice.js 4. Enjoy your generated PDF
  94. Behind_the_scenes Connecting the dots

  95. Behind_the_scenes 1. Build your components 2. Render the HTML on

    the server 3. Pass the HTML to wkhtmltopdf Similar to react-emails
  96. Same previous process as with react-emails

  97. How it works

  98. server/createPDF.js

  99. None
  100. Is there a better way?

  101. Headless browsers

  102. Headless browsers

  103. None
  104. None
  105. Q: What is the difference between Puppeteer, Selenium / WebDriver,

    and PhantomJS?
  106. “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”
  107. “Puppeteer bundles Chromium to ensure that the latest features it

    uses are guaranteed to be available.” package.json
  108. Q: Ok, but why Puppeteer?

  109. • CSS support • Export to PDF directly Benefits

  110. None
  111. Consider navigation to be finished when there are no network

    connections for at least 500 ms
  112. None
  113. Auth & Cookies

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

  115. None
  116. We can now fetch the data and render the report

    for that user
  117. None
  118. Takeaways

  119. Takeaways • React components benefits can be used outside a

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

    typical web application • “Good enough” is fine • Ship it
  121. fjaguero fjaguero Thanks! fjaguero.com bit.ly/react-emails-pdf