Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client-side printing with Vue #3532

Merged
merged 60 commits into from
Aug 16, 2023
Merged

Conversation

carlobeltrame
Copy link
Member

@carlobeltrame carlobeltrame commented Jun 23, 2023

In a nutshell: Replaces React with Vue 3, but keeps the client-side printing capabilities of react-pdf. It looks and feels exactly like the existing react-pdf implementation, but is implemented using Vue components instead of React JSX files.

How does this work?

React-pdf consists of several modules:

  • @react-pdf/renderer is a React renderer which takes a React component structure as input and produces a description of the PDF as a JS object as the output
  • @react-pdf/layout takes this object as input, and uses yoga (a JS flexbox implementation which is commonly used in React Native) and some other magic to calculate the dimensions of all elements, and writes the dimensions into the object.
  • @react-pdf/render takes the object with dimensions, and translates it into instructions for pdfkit (a low-level PDF creation library)
  • There are some other modules which are used by layout and render, which aren't important for the big picture

Only the first module (@react-pdf/renderer) actually has anything to do with React. All the other modules are framework-agnostic.

This PR adds a Vue 3 custom renderer which does the same as @react-pdf/renderer does, but with Vue 3. There have been several attempts at similar renderers documented on the internet [1] [2], although none of them went far enough to be really practical.

The biggest hurdle I had to overcome was that we cannot install Vue 2 and Vue 3 alongside each other in our frontend. For this reason, I created a new separate pdf module as a Vue 3 project. This module is built using vite build --watch whenever some PDF code is changed, and the resulting output file is imported in our normal frontend code. The bundled pdf module code is ~400KB and is typically rebuilt within less than a second. This way, we can develop with hot module reloading on the PDF preview.

Additional features

  • We can write more CSS-like styles in custom <pdf-style></pdf-style> blocks in the .vue files
  • Works seamlessly in web workers, because the core of Vue 3 (unlike Vue 2 and React) does not make any assumptions about the context it is run in
  • Some convenience improvements over react-pdf (e.g. not all text has to be strictly wrapped in <Text> tags, global helpers such as this.$date or this.$tc or this.api are more natural to use in Vue than in React/JSX)
  • The renderer code potentially could become a separate NPM package in the future, or be integrated into the react-pdf repository
  • This approach with separated component structure and PDF rendering lowers our vendor lock-in a little. E.g. http://pdfmake.org also uses a declarative document structure object and renders a PDF using pdfmake.
  • While I was at it, I implemented similar layout and typography improvements like the ones we introduced in nuxt print in Improve print nuxt design #3577

Open TODOs

  • Auto-remove optional display: flex statements during compile time (flex is the default display in react-pdf) not doing that for now, to avoid cascading style issues
  • Move prepareInMainThread to a separate entrypoint so the fonts aren't loaded in the main thread
  • Disable v-for key warning and remove all :key attrs
  • Remove everything related to react
  • Add some (dummy) tests with vitest
  • remove demo code
  • Fix frontend test setup
  • Try to remove the components in pdf/renderer/components, adjust the htmlToPdfElementMap, and see how that feels for devs

@manuelmeister manuelmeister added deploy! Creates a feature branch deployment for this PR and removed deploy! Creates a feature branch deployment for this PR labels Jun 27, 2023
@carlobeltrame carlobeltrame force-pushed the vue-pdf branch 3 times, most recently from e5c05b0 to d2a6438 Compare July 1, 2023 11:09
@carlobeltrame carlobeltrame marked this pull request as ready for review July 1, 2023 11:10
@carlobeltrame carlobeltrame added the deploy! Creates a feature branch deployment for this PR label Jul 1, 2023
@manuelmeister manuelmeister removed the deploy! Creates a feature branch deployment for this PR label Jul 1, 2023
@manuelmeister
Copy link
Member

manuelmeister commented Jul 1, 2023

Deployment is generating errors: https://github.com/ecamp/ecamp3/actions/runs/5431444930

@carlobeltrame carlobeltrame added the deploy! Creates a feature branch deployment for this PR label Jul 2, 2023
@github-actions
Copy link

github-actions bot commented Jul 2, 2023

Feature branch deployment currently inactive.

If the PR is still open, you can add the deploy! label to this PR to trigger a feature branch deployment.

docker-compose.yml Outdated Show resolved Hide resolved
docker-compose.yml Outdated Show resolved Hide resolved
Copy link
Contributor

@BacLuc BacLuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Thank you very much

Copy link
Member

@pmattmann pmattmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions for the CoreMeeting:

  • Does nodeOps.js need to be complete?
  • How big do we estimate the maintenance effort?
  • How do we determine if there are additional requirements for nodeOps.js in the future?

@manuelmeister manuelmeister added the Meeting Discuss Am nächsten Core-Meeting besprechen label Aug 15, 2023
@manuelmeister manuelmeister temporarily deployed to feature-branch August 15, 2023 11:32 — with GitHub Actions Inactive
@manuelmeister manuelmeister removed the Meeting Discuss Am nächsten Core-Meeting besprechen label Aug 15, 2023
@carlobeltrame carlobeltrame temporarily deployed to feature-branch August 15, 2023 18:54 — with GitHub Actions Inactive
This makes us more robust against new elements which react-pdf might
introduce in the future.
@carlobeltrame carlobeltrame temporarily deployed to feature-branch August 16, 2023 12:21 — with GitHub Actions Inactive
@carlobeltrame carlobeltrame merged commit e00716b into ecamp:devel Aug 16, 2023
23 checks passed
@carlobeltrame carlobeltrame deleted the vue-pdf branch August 16, 2023 13:13
@carlobeltrame carlobeltrame mentioned this pull request Nov 10, 2023
54 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy! Creates a feature branch deployment for this PR
Projects
Development

Successfully merging this pull request may close these issues.

None yet

4 participants