MatthewHerbst / react-to-print

Print React components in the browser. Supports Chrome, Safari, Firefox and EDGE
MIT License
2.14k stars 221 forks source link

react-to-print custom print html content dev vs prod discrepancy #681

Closed sammyhajomar closed 7 months ago

sammyhajomar commented 9 months ago

I am utilizing react-to-print to extract the html of a component in order to generate a PDF with the same styles

const handlePrint = useReactToPrint({
        content: () => componentRef.current,
        copyStyles: true,
        print: async (printIframe: HTMLIFrameElement) => {
            const document = printIframe.contentDocument;
            if (document) {
                const html = document.getElementsByTagName('html')[0];
                try {
                    // fetch puppet and pass htmlString as body
                    const result = await fetch('/api/puppeteer', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({ html: html?.outerHTML })
                    });

The issue here is I am getting different outputs for html.outerHTML between dev and prod. In dev, all styles work well, but in a prod build none of the styles are loaded. Not sure if this is a bug with nextjs interacting with react-to-print.

Here are the first 1,000 characters of html.outerHTML:

In dev env:

<html><head><style>
        @page {
            /* Remove browser default header (title) and footer (url) */
            margin: 0;
        }
        @media print {
            body {
                /* Tell browsers to print background colors */
                -webkit-print-color-adjust: exact; /* Chrome/Safari/Edge/Opera */
                color-adjust: exact; /* Firefox */
            }
        }
    </style><style id="react-to-print-0">*, ::before, ::after { box-sizing: border-box; border-width: 0px; border-style: solid; border-color: rgb(229, 231, 235); }
::before, ::after { --tw-content: ''; }
html { line-height: 1.5; text-size-adjust: 100%; tab-size: 4; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-feature-settings: normal; font-variation-settings: normal; }
body { margin: 0px; line-height: inheri

In prod build:

<html><head><style>
        @page {
            /* Remove browser default header (title) and footer (url) */
            margin: 0;
        }
        @media print {
            body {
                /* Tell browsers to print background colors */
                -webkit-print-color-adjust: exact; /* Chrome/Safari/Edge/Opera */
                color-adjust: exact; /* Firefox */
            }
        }
    </style><link rel="preload" href="/_next/static/css/af4209565143e128.css" as="style" crossorigin=""><link rel="stylesheet" href="/_next/static/css/af4209565143e128.css" crossorigin="" data-n-g=""><style id="react-to-print-2">@keyframes go2264125279 { 
  0% { transform: scale(0) rotate(45deg); opacity: 0; }
  100% { transform: scale(1) rotate(45deg); opacity: 1; }
}
@keyframes go3020080000 { 
  0% { transform: scale(0); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes go463499852 { 
  0% { transform: scale(0) rotate(90deg); opacity: 0; }
  100% { transform: scale
MatthewHerbst commented 9 months ago

Hello. react-to-print doesn't interact with your build system or framework in any way. We just take whatever styles exist currently on the page. I would guess that the styles you need aren't being included properly in your production build. This is almost certainly an issue with your next.js configuration, which unfortunately isn't something I am very familiar with so I can't offer much help. It's probably a better question for StackOverflow honestly: "why are my production styles and dev styles different" etc

sammyhajomar commented 9 months ago

@MatthewHerbst but when I do allow for printing of the component using <ReactToPrint/>, the styles are all there and there is no discrepancy. So it seems to me like the html that is returned in the custom print function is different to the one that is used to print in <ReactToPrint />

MatthewHerbst commented 9 months ago

Hmm. The same iframe that is used for the regular printing is also what's given to the print callback (code), so not sure what would be different about that.

To be clear here: the issue is that the custom print function isn't getting the right content, or is this still a dev/prod issue

siaikin commented 9 months ago

@sammyhajomar In the first 1000 characters of the content you gave for the production environment, the styles are loaded via relative paths and no domain name is specified which may be the reason why the styles are not loaded.