bpampuch / pdfmake

Client/server side PDF printing in pure JavaScript
http://pdfmake.org
Other
11.61k stars 2.04k forks source link

Clientside Feature Suggestion: Web Worker Compatibility #38

Open dlesser opened 10 years ago

dlesser commented 10 years ago

One thing that would enable more scaling client-side scenarios would be if pdfMake can run in a web worker compatible mode. One thing I'm seeing with more complex PDFs in IE and Firefox is script time outs, which probably is to be expected if most of the logic runs on the UI thread.

Trying to use from a web worker just to see how many dependencies on window DOM, initially get errors in sections of pdfmake.js using the window.navigator object.

in pdfWebWorker.js importScripts fails. Thinking it might be possible to put shim components before invoking importScripts in the web worker....or fork and create custom build of pdfmake... importScripts("pdfmake.js", "vfs_fonts.js");

(Thought maybe it had a chance if the same source code was managing to run on node.js there couldn't be that many dependencies on DOM.)

Great tool so far. Thanks.

bpampuch commented 10 years ago

Great idea!!! BTW - could you share a sample doc-definition-object which causes the script timeout? I'm getting back to pdfmake after a long break and I'm trying to focus on the first milestone (performance improvements).

dlesser commented 10 years ago

Sure, gladly. Part of the initial timeout was that I am using other cpu intensive scripts (vis.js and html2canvas) and pdfmake is the last set of scripts in the pipeline. So it doesn’t always seem consistent in causing timeout.

I get this in firefox, and intermittently in IE: “A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete.

Script: http://localhost:52165/Scripts/pdfmake.js:3813” Thanks!

var docDefinition = { content: [

                {
                    columns: [

                        {
                            // if you specify width, image will scale proportionally
                            image: 'companyLogo',
                            width: 150
                        },

           { text: 'SummarySummary Summary', style: 'header' }

                    ],

                    // optional space between columns
                    columnGap: 10
                }
            ,

            {
                table: {
                    // headers are automatically repeated if the table spans over multiple pages
                    // you can declare how many rows should be treated as headers
                    headerRows: 0,
                    widths: ['*', '*'],
                    style: 'tbl',
                    body: [

                      [{
                          stack: [{ text: [{ text: 'XYZ:', bold: true }, { text: "lorem ipsum" }], style: 'field' },

                              { text: [{ text: 'ABC:', bold: true }, { text: "lorem ipsum" }], style: 'field' },

                              { text: [{ text: '123:', bold: true }, { text: "lorem ipsum" }], style: 'field' },

                          ]
                      }, { text: 'Patient Name:' }]
                    ]
                }
            },
            //{
            //    canvas: [
            //   {
            //       type: 'rect',
            //       x: 0,
            //       y: 0,
            //       w: 600,
            //       h: 260,
            //       r: 5,
            //       dash: { length: 2 },
            //       // lineWidth: 10,
            //       lineColor: 'blue',
            //       fillOpacity: .7,
            //       strokeOpacity: 1
            //   }]
            //},
             {
                 image: 'patientTimeline'
                 //width:680
             },
            {
                columns: [
                  {
                      // auto-sized columns have their widths based on their content
                      width: '*',
                      text: 'First column'
                  },
                  {
                      // star-sized columns fill the remaining space
                      // if there's more than one star-column, available width is divided equally
                      width: '*',
                      text: 'Second column'
                  },

                {
                    // star-sized columns fill the remaining space
                    // if there's more than one star-column, available width is divided equally
                    width: '*',
                    text: '3 column'
                }
                ],
                // optional space between columns
                columnGap: 10
            }

            ],

            styles: {
                header: {
                    fontSize: 16,
                    bold: true,
                    color: 'blue',
                    alignment: 'center'
                },
                field: {
                    fontSize: 10,
                    alignment: 'justify'
                },
                tbl: {

                    hLineColor: 'blue',
                    vLineColor: 'blue',
                    vLineWidth: 2,
                    hLineWidth: 2
                }
            },

            images: {
                patientTimeline: 'data:image/png;base64,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AAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAg0nX/D3xkbxtHv5JbAAAAAElFTkSuQmCC',
                companyLogo: 'data:image/png;base64,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AAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAgJKwCAAAAAISEVQAAAACAkLAKAAAAABASVgEAAAAAQsIqAAAAAEBIWAUAAAAACAmrAAAAAAAhYRUAAAAAICSsAgAAAACEhFUAAAAAgJCwCgAAAAAQElYBAAAAAELCKgAAAABASFgFAAAAAAgJqwAAAAAAIWEVAAAAACAkrAIAAAAAhIRVAAAAAICQsAoAAAAAEBJWAQAAAABCwioAAAAAQEhYBQAAAAAICasAAAAAACFhFQAAAAAg0nX/D3xkbxtHv5JbAAAAAElFTkSuQmCC'
            }
        };

Daniel Lesser | Technical Director, Business Performance Services | NTT DATA, Inc. | m. +1.303.808.5731 | daniel.lesser@nttdata.commailto:daniel.lesser@nttdata.com | NTT DATA Americashttp://americas.nttdata.com/ | Twitter: @https://twitter.com/#!/NTTDAmericasASNTTDAmericasAS | LinkedIn: NTTDATAAmericashttp://www.linkedin.com/company/ntt-data-americas

From: bpampuch [mailto:notifications@github.com] Sent: Friday, June 13, 2014 11:49 AM To: bpampuch/pdfmake Cc: Lesser, Daniel Subject: Re: [pdfmake] Clientside Feature Suggestion: Web Worker Compatibility (#38)

Great idea!!! BTW - could you share a sample doc-definition-object which causes the script timeout? I'm getting back to pdfmake after a long break and I'm trying to focus on the first milestone (performance improvements).

— Reply to this email directly or view it on GitHubhttps://github.com/bpampuch/pdfmake/issues/38#issuecomment-46040264.


Disclaimer:This email and any attachments are sent in strictest confidence for the sole use of the addressee and may contain legally privileged, confidential, and proprietary data. If you are not the intended recipient, please advise the sender by replying promptly to this email and then delete and destroy this email and any attachments without any further use, copying or forwarding

philjoseph commented 10 years ago

Hello - We are considering using pdfmake to generate one page reports and we are concerned with performance. We are generating simple one page PDF that is 50Kbyte that mostly contain one PNG generated by Google chart that is 20Kbyte. The generation of such a report can take up to 30 second!! We tried to profile that but with no success for now. Any hint about how to profile PDFmake doc generation? If we cannot optimize, we will consider using web worker and at least unfreeze the UI

giulioprovasi commented 9 years ago

+1, I need to generate a report of ~1mb and it takes around 5 seconds, which is quite long when the UI freeze. I am actually trying to do my custom web worker integration in my angular application, but would be awesome to see this functionality embedded in pdfmake

jthoenes commented 9 years ago

We would be happy to accept a pull request ;-)

giulioprovasi commented 9 years ago

I'll start by learning how webworkers work exactly :) but why not, I'll take a look. For now the problem is the fileSaver lib which use view.document directive which isn't allowed in web workers, any idea how to solve this ?

jthoenes commented 9 years ago

The filesaver is (surprise) for saving/downloading files - this will need user interaction anyway and therefore cannot be done in a web worker.

So my approach would be to split the generation of the PDF and the handling of its output - download, open and so on. Then the 'slow' generation is done, while the interaction stays in the browser.

Make sure to create integration tests which indicate when someone accidentally breaks web worker compatibility again.

Best regards Johannes Am 27.03.2015 10:48 schrieb "kitensei" notifications@github.com:

I'll start by learning how webworkers work exactly :) but why not, I'll take a look. For now the problem is the fileSaver lib which use view.document directive which isn't allowed in web workers, any idea how to solve this ?

— Reply to this email directly or view it on GitHub https://github.com/bpampuch/pdfmake/issues/38#issuecomment-86882582.

hujhax commented 9 years ago

Hi all -- I've started looking into this one for my own nefarious porpoises. So it looks like, for web workers, you can throw just about anything 'over the wall' between the main thread and the web worker via a postMessage so long as it's serializable. So: no functions, no circular references.

So I'm guessing on the input end, I can throw in the doc object -- it's a big object, but it's serializable. And then on the other end, the web worker could get the buffer back -- again, huge, but serializable.

So then the web worker could respond to a message with a doc object by calling _createDoc, and making the callback a postMessage that sends the resulting buffer back to the main thread.

Then the toughest part is figuring out how to import some subset of pdfMake that a web worker can successfully run. Maybe it just imports all of pdfMake, and I pepper pdfMake with guards against running in not-a-window?

Does this sound vaguely sane?

hujhax commented 9 years ago

Huh -- I kind of have it working, to my surprise. The (giant) drawback is that your document object -- the content, the footers, and whatnot -- can't include any function definitions, because those can't be serialized. This might be an insuperable problem.

jthoenes commented 9 years ago

Yes, that's true.

dlesser commented 9 years ago

Very cool. But is it not possible to eval() within a webworker? Didn't turn up anything on stack overflow so guess have to experiment. And translate to obj= {'functionName':'functionAsString'} - > translate to webWorkerObj[functionName]=function(){eval(obj.functionName)} ... it may be too tricky even if this works in principal.

dlesser commented 9 years ago

Example #1: Create a generic "asynchronous eval()" - https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Example_.231.3A_Create_a_generic_.22asynchronous_eval().22

hujhax commented 9 years ago

Ooh, interesting idea. I'm also wondering if it's possible to pass along a filename, put an object that maps names to functions in that file:

{
    specialFooter: function() {
        return (new Date()).toString();
    }
}

... and then have pdfMake import that file as a module, and then replace mentions of that function name with the function itself:

footer: {
    functionName: "specialFooter"
}

... not sure if that'd work, though.

hujhax commented 9 years ago

For my project, I'm most likely going to:

  1. Create some kind of string interpolation to get the page number in the footer, and
  2. Add some new layouts to registerDefaultTableLayouts, including one for horizontal rules.

Between those two, I shouldn't have to pass in any functions (fingers crossed).

skylize commented 9 years ago

If it's anything like messages to frames, it should be almost trivial to make many functions "callable" from across the wall.

// fn is a string containing method name
function handleMsg(evt) {
  if (evt.data && evt.data.fn) 
    pdfMake[evt.data.fn]()
}
window.addEventListener('message', handleMsg, false)
hujhax commented 9 years ago

Yup -- the main issue is making sure there aren't any functions in the doc object. Plus there are a few adjustments to make to the pdfmake code itself, so it doesn't freak out about being called in a web-worker situation.

hujhax commented 9 years ago

Note that pdfmake in a web work isn't working when deployed to iOS Safari, because of this issue: https://github.com/lodash/lodash/issues/313

Sheep-y commented 8 years ago

I can run pdfmake in webworker. It is stupid:

var document = { 'createElementNS': function(){ return {}; } };

The offending code calls documentcreateElementNS, but it is not really used. I just return a dummy JS object - not even an Element - and it happily gives me a pdf!

It is not that hard to update the code to support web worker, or is it?

P.S. vfs_fonts.js use window, unavailable in worker, which is also... easy to fix.

ramonsan commented 8 years ago

I have a tidy workaround to avoid passing the footer as a function. First, I transform the footer function in a footer template:

Instead of:

footer : function (currentPage, pageCount) { return currentPage' + ' of ' + pageCount}),

I write:

footerTpl : '{{currentPage}}' + ' of ' + '{{pageCount}}',

Then I prepare the whole pdfTemplate and send it to the web worker, so in worker.js I parse the footer string into the real footer:

self.onmessage = function (e) {
    if (e.data.footerTpl) {
      e.data.footer = function (currentPage, pageCount) {
        var footer = e.data.footerTpl.replace('{{currentPage}}', currentPage);
        footer = footer.replace('{{pageCount}}', pageCount);
        return footer;
      };
    }
    pdfMake.createPdf(e.data).getBase64(function (base64) {
      self.postMessage(base64);
    });
  };

And you have a nice PDF with page count on footer.

Sasha0430 commented 7 years ago

Hi dlesser.

How are you? I would like to discuss with you about vfs_fonts.js problem in web worker. I used the solution of Sheep-y and resolved pdfmake.js importing problem but vfs_font.js is not working in web worker. Would you let me know the solution? I think you already resolved completely.

Thanks. Sasha

ModMorph commented 7 years ago

Sorry don't have it...I ended up using server side solution.

leedongwei commented 7 years ago

I've managed to make web worker work reasonably well with pdfmake, demo code: https://gist.github.com/leedongwei/6015450165b70a32b72cdebc073714ab

@bpampuch If this looks like a reasonable workaround, I'll make a pull request to update the documentation.

liborm85 commented 7 years ago

@leedongwei Any help is welcome. But first we should solve the incompatibility with web worker inside pdfmake.

My findings and suggestions:

Problem 1:

window = this;

pdfmake using window property which is only in the browser. I can fix it, I use global instead of window (in vfs_fonts.js file probably this).


Problem 2:

document = { createElementNS: function () { return {}; } };

createElementNS is used in external library FileSaver.js, see: https://github.com/eligrey/FileSaver.js/blob/aa9f4e0e03bd1892482ff5e24ca91d42312dbf18/FileSaver.js#L28 Is used to download a file, in web worker is not used but is in source file. I don't know how solve it now. But I try it.


Big problem 3: Problem with functions - https://github.com/bpampuch/pdfmake/issues/38#issuecomment-229358463 If I can send message to worker is needed convert it to string, because only a string can be sent. Can not be send as myWorker.postMessage(docDefinition). docDefinition must be converted to string: myWorker.postMessage( JSON.stringify(docDefinition) );, but JSON.stringify not support functions.

Solution: Make another string converter with support functions implemented in pdfmake.

During creation Worker in script, I suppose is not good include full pdfmake script? So we need to do another script file with class - pdfMakePreparer (Any better ideas?), which will only allow safely convert docDefinition to string or/and call postMessage on Worker with stringDocDefinition. And in worker skript will be used standard pdfmake method pdfMake.createPdf( dd ), where createPdf if they receive docDefiniton as string through safety convert string to docDefinition.

Examples:

var docDefinition = {
 // ... standard docDefinition
}

myWorker = new Worker('worker.js');

pdfMakePreparer.postMessage(myWorker, docDefinition); // internaly this make convert docDefinition to string with own JSON.stringify and call myWorker.postMessage(stringDocDefinition);

// or
var stringDocDefinition = pdfMakePreparer.prepareDocDefinition(docDefinition); // only internaly convert
myWorker.postMessage(stringDocDefinition );

worker.js:

onmessage = function(e) {

  // If is e.data as string make transform with own JSON.parse from string to docDefinition inside createPdf
  var doc = pdfMake.createPdf(e.data)
  doc.getBlob();
  // etc.
};

I saw that guys in the project OpenSlides using web worker with this hacks - https://github.com/OpenSlides/OpenSlides/blob/935a2a724544d0be89b6d143488cd649712cd068/openslides/core/static/js/core/pdf-worker.js , @emanuelschuetze and @tsiegleauq any ideas or feedback for the proposed solutions?

And all, any other ideas?

tsiegleauq commented 7 years ago

I am on phone and cannot use @ function. Somebody please @'s Finn Stutzenstein from OpenSlides.

On Apr 20, 2017 11:16, "Libor M." notifications@github.com wrote:

@leedongwei https://github.com/leedongwei Any help is welcome. But first we should solve the incompatibility with web worker inside pdfmake.

My findings and suggestions:

Problem 1:

window = this;

pdfmake using window property which is only in the browser. I can fix it, I use global instead of window (in vfs_fonts.js file probably this).

Problem 2:

document = { createElementNS: function () { return {}; } };

createElementNS is used in external library FileSaver.js, see: https://github.com/eligrey/FileSaver.js/blob/ aa9f4e0e03bd1892482ff5e24ca91d42312dbf18/FileSaver.js#L28 Is used to download a file, in web worker is not used but is in source file. I don't know how solve it now. But I try it.

Big problem 3: Problem with functions - #38 (comment) https://github.com/bpampuch/pdfmake/issues/38#issuecomment-229358463 If I can send message to worker is needed convert it to string, because only a string can be sent. Can not be send as myWorker.postMessage( docDefinition). docDefinition must be converted to string: myWorker.postMessage( JSON.stringify(docDefinition) );, but JSON.stringify not support functions.

Solution: Make another string converter with support functions implemented in pdfmake.

During creation Worker in script, I suppose is not good include full pdfmake script? So we need to do another script file with class - pdfMakePreparer (Any better ideas?), which will only allow safely convert docDefinition to string or/and call postMessage on Worker with stringDocDefinition. And in worker skript will be used standard pdfmake method pdfMake.createPdf( dd ), where createPdf if they receive docDefiniton as string through safety convert string to docDefinition.

Examples:

var docDefinition = { // ... standard docDefinition }

myWorker = new Worker('worker.js');

pdfMakePreparer.postMessage(myWorker, docDefinition); // internaly this make convert docDefinition to string with own JSON.stringify and call myWorker.postMessage(stringDocDefinition);

// or var stringDocDefinition = pdfMakePreparer.prepareDocDefinition(docDefinition); // only internaly convert myWorker.postMessage(stringDocDefinition );

worker.js:

onmessage = function(e) {

// If is e.data as string make transform with own JSON.parse from string to docDefinition inside createPdf var doc = pdfMake.createPdf(e.data) doc.getBlob(); // etc. };


I saw that guys in the project OpenSlides using web worker with this hacks

And all, any other ideas?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bpampuch/pdfmake/issues/38#issuecomment-295646625, or mute the thread https://github.com/notifications/unsubscribe-auth/AJwkyDGwD6jrlk7abIl-uI-Gb9_4xvZaks5rxyJsgaJpZM4CEFpJ .

liborm85 commented 7 years ago

@FinnStutzenstein ping ;-)

FinnStutzenstein commented 7 years ago

Hi

Yes, we at OpenSlides use exactly these three hacks to use PdfMake within web workers.

Problem 1:

Should be easy to fix.

Problem 2:

To use WebWorkers you have to have (at least) two scripts. In the WebWorker script just the casting from docDefinition --> blob/b64/.. is done. So the worker script has not to include FileSaver. Also for a production use this is helpful, because you may handle these two js files different. The worker script should not be squashed together in the main js sourcemap, but rather stay alone.

Problem 3:

  1. Use eval. Our team thought about that, because the functions passe dare very small and simple. But there are two main reasons against eval:

    • Larger functions are not nice to handle as strings
    • May not in this scenario - where the string is constant - but when having user input (may for formatting the footer string) eval is a huge security issue.
  2. Templates: Our current solution, as we cannot pass functions. Not very nice, but just for the two places, it's ok. -> Not ok for a upstream solution.

  3. Do some prerendering. Convert the docDefinition in something serialize able, what has to be fully rendered in the worker. This should not take a long time. Unfortunately, I've not looked very deep in the PdfMake source, that I can evaluate, if this is a good option. But, as a fact, we have to get a string, so some pre evaluating has to be done here.

If this is implemented, PdfMake should hide the WebWorkers by just giving the option, to generate the pdf async. A setting to specify the worker filename would be great. And two separate files are necessary and the worder script should not contain the whole PdfMake source.

liborm85 commented 7 years ago

@FinnStutzenstein Hi. Thanks for your experiences and ideas.

As first step i'm fixed compatibility with running in worker script (solves problem 1 and temporally problem 2), commits: https://github.com/bpampuch/pdfmake/commit/5fd7bc9fa3d13014bfc3797cd7f50935f363bcd0, https://github.com/bpampuch/pdfmake/commit/33df9bbec76b358bec8d08bc49a1d2892445a3fa.

I will try to think about a complex solution with support functions. And possibly any pdfmake async class/script.

shayts commented 7 years ago

Any one can provide an example on how to use pdfMake in a web-worker in angular 4?

Thanks.

skylize commented 7 years ago

@liborm85

Big problem 3: Problem with functions - #38 (comment) If I can send message to worker is needed convert it to string, because only a string can be sent. Can not be send as myWorker.postMessage(docDefinition). docDefinition must be converted to string: myWorker.postMessage( JSON.stringify(docDefinition) );, but JSON.stringify not support functions.

If you are creating the full doc definition outside the web worker, why do you need pdfmake at all inside the worker? Why not just message over a url blob of the complete pdf?

FinnStutzenstein commented 7 years ago

If you are creating the full doc definition outside the web worker, why do you need pdfmake at all inside the worker? Why not just message over a url blob of the complete pdf?

Did I get you right that you want to create the pdf blob outside of the worker and just pass the url to the worker? If so, you get this wrong: The creation of the doc definition is fast; we want to source out the converting json->pdf (doc definition -> blob/b64) in fact that this can took several minutes. For this conversion we need like 98% of pdfmake (except the download thing) inside of the web worker. The creation of the doc definition has nothing to do with pdfmake. This is just placing javascript arrays and objects with data in the right format that pdfmake can parse this.

mathias22osterhagen22 commented 2 years ago

Here is a workaround I used based on a response from stack overflow: https://stackoverflow.com/a/33206568/12530707

index.html

<script>
//* Conversion func
function base64ToBlob(base64, type) {
    var bytes = atob(base64), len = bytes.length;
    var buffer = new ArrayBuffer(len), view = new Uint8Array(buffer);
    for (var i = 0; i < len; i++)
        view[i] = bytes.charCodeAt(i) & 0xff;
    return new Blob([buffer], { type: type });
}

//* Create new worker
var pdfworker = new Worker('./js/pdfworker.js');
pdfworker.onmessage = function (evt) {
    saveAs(base64ToBlob(evt.data, 'application/pdf'), 'MyPDF.pdf');
};

//* Generation
let pdfDefinition = {}; //your pdf object here
pdfworker.postMessage(pdfDefinition);  //Call to generate PDf
</script>

pdfworker.js

var document = { 'createElementNS': function () { return {} } };
var window = this;
importScripts('pdfmake.min.js', 'vfs_fonts.js');

(function () {
    var doc, current, context_stack;

    function set(data) {
        data.footer = (currentPage, pageCount) => { return { text: "Page " + currentPage.toString() + ' of ' + pageCount, style: "footer" }; }; //I putted it there but you can use this tips : https://github.com/bpampuch/pdfmake/issues/38#issuecomment-229358463
        doc = data;
        if (!doc.content) doc.content = [];
        current = doc.content;
        context_stack = [current];
    }

    onmessage = function (evt) {
        set(evt.data); //Bypass DOM
        pdfMake.createPdf(doc).getBase64(function (base64) {
            postMessage(base64); //Send back the base64 to index.html
        });
    };
})();
danielstevenberger commented 2 years ago

Does anyone have a workaround for getting this to work in an Angular 13 web-worker?

liborm85 commented 2 years ago

There are no known problems in Angular now. Describe your problems and attach runnable example for reproduce issue.

danielstevenberger commented 2 years ago

There are no known problems in Angular now. Describe your problems and attach runnable example for reproduce issue.

I'm trying to create a pdf inside of an Angular web worker. I created a web worker following these steps. https://angular.io/guide/web-worker

import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';

addEventListener('message', ({ data }) => {
  const response = `worker response to ${data}`;
  postMessage(response);
});

When importing pdfMake, I'm receiving numerous errors that I believe are from dependencies on window DOM. I haven't had any luck with the workarounds discussed above. Please let me know if there is a working example or any ideas for a solution.

danielstevenberger commented 2 years ago

There are no known problems in Angular now. Describe your problems and attach runnable example for reproduce issue.

I'm trying to create a pdf inside of an Angular web worker. I created a web worker following these steps. https://angular.io/guide/web-worker

import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';

addEventListener('message', ({ data }) => {
  const response = `worker response to ${data}`;
  postMessage(response);
});

When importing pdfMake, I'm receiving numerous errors that I believe are from dependencies on window DOM. I haven't had any luck with the workarounds discussed above. Please let me know if there is a working example or any ideas for a solution.

The only solution I found that worked was to add "skipLibCheck": true, to the ts-config.

The errors I was receiving were mainly in node_modules/typescript/lib/lib.webworker.d.ts and node_modules/typescript/lib/lib.dom.d.ts. When importing other modules into the web worker, I did not have this issue.

Here is the full log.

Error: node_modules/typescript/lib/lib.webworker.d.ts:25:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: ImportExportKind, TableKind, ValueType, ExportValue, Exports, ImportValue, Imports, ModuleImports, name, AlgorithmIdentifier, BigInteger, BinaryData, BlobPart, BodyInit, BufferSource, CanvasImageSource, DOMHighResTimeStamp, DOMTimeStamp, EventListenerOrEventListenerObject, Float32List, FormDataEntryValue, GLbitfield, GLboolean, GLclampf, GLenum, GLfloat, GLint, GLint64, GLintptr, GLsizei, GLsizeiptr, GLuint, GLuint64, HashAlgorithmIdentifier, HeadersInit, IDBValidKey, ImageBitmapSource, Int32List, MessageEventSource, NamedCurve, OnErrorEventHandler, PerformanceEntryList, ReadableStreamController, ReadableStreamDefaultReadResult, ReadableStreamReader, RequestInfo, TexImageSource, TimerHandler, Transferable, Uint32List, VibratePattern, XMLHttpRequestBodyInit, BinaryType, ClientTypes, ColorGamut, ColorSpaceConversion, ConnectionType, EndingType, FontFaceLoadStatus, FontFaceSetLoadStatus, HdrMetadataType, IDBCursorDirection, IDBRequestReadyState, IDBTransactionMode, ImageOrientation, KeyFormat, KeyType, KeyUsage, MediaDecodingType, MediaEncodingType, NotificationDirection, NotificationPermission, PermissionName, PermissionState, PredefinedColorSpace, PremultiplyAlpha, PushEncryptionKeyName, PushPermissionState, ReferrerPolicy, RequestCache, RequestCredentials, RequestDestination, RequestMode, RequestRedirect, ResizeQuality, ResponseType, SecurityPolicyViolationEventDisposition, ServiceWorkerState, ServiceWorkerUpdateViaCache, TransferFunction, VisibilityState, WebGLPowerPreference, WorkerType, XMLHttpRequestResponseType

25 interface AddEventListenerOptions extends EventListenerOptions {
   ~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:25:1
    25 interface AddEventListenerOptions extends EventListenerOptions {
       ~~~~~~~~~
    Conflicts are in this file.

Error: node_modules/typescript/lib/lib.webworker.d.ts:1094:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'DOMMatrixReadOnly' must be of type '{ new (init?: string | number[] | undefined): DOMMatrixReadOnly; prototype: DOMMatrixReadOnly; fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; fromMatrix(other?: DOMMatrixInit | undefined): DOMMatrixReadOnly; toString(): string; }', but here has type '{ new (init?: string | number[] | undefined): DOMMatrixReadOnly; prototype: DOMMatrixReadOnly; fromFloat32Array(array32: Float32Array): DOMMatrixReadOnly; fromFloat64Array(array64: Float64Array): DOMMatrixReadOnly; fromMatrix(other?: DOMMatrixInit | undefined): DOMMatrixReadOnly; }'.

1094 declare var DOMMatrixReadOnly: {
                 ~~~~~~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:3825:13
    3825 declare var DOMMatrixReadOnly: {
                     ~~~~~~~~~~~~~~~~~
    'DOMMatrixReadOnly' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:1594:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'FormData' must be of type '{ new (form?: HTMLFormElement | undefined): FormData; prototype: FormData; }', but here has type '{ new (): FormData; prototype: FormData; }'.

1594 declare var FormData: {
                 ~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:5209:13
    5209 declare var FormData: {
                     ~~~~~~~~
    'FormData' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:2211:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'Notification' must be of type '{ new (title: string, options?: NotificationOptions | undefined): Notification; prototype: Notification; readonly permission: NotificationPermission; requestPermission(deprecatedCallback?: NotificationPermissionCallback | undefined): Promise<...>; }', but here has type '{ new (title: string, options?: NotificationOptions | undefined): Notification; prototype: Notification; readonly permission: NotificationPermission; }'.

2211 declare var Notification: {
                 ~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:9853:13
    9853 declare var Notification: {
                     ~~~~~~~~~~~~
    'Notification' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:2970:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'URL' must be of type '{ new (url: string | URL, base?: string | URL | undefined): URL; prototype: URL; createObjectURL(obj: Blob | MediaSource): string; revokeObjectURL(url: string): void; }', but here has type '{ new (url: string | URL, base?: string | URL | undefined): URL; prototype: URL; createObjectURL(obj: Blob): string; revokeObjectURL(url: string): void; }'.

2970 declare var URL: {
                 ~~~

  node_modules/typescript/lib/lib.dom.d.ts:13865:13
    13865 declare var URL: {
                      ~~~
    'URL' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5597:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onmessage' must be of type '((this: Window, ev: MessageEvent<any>) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: MessageEvent<any>) => any) | null'.

5597 declare var onmessage: ((this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any) | null;
                 ~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17551:13
    17551 declare var onmessage: ((this: Window, ev: MessageEvent) => any) | null;
                      ~~~~~~~~~
    'onmessage' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5598:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onmessageerror' must be of type '((this: Window, ev: MessageEvent<any>) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: MessageEvent<any>) => any) | null'.

5598 declare var onmessageerror: ((this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any) | null;
                 ~~~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17552:13
    17552 declare var onmessageerror: ((this: Window, ev: MessageEvent) => any) | null;
                      ~~~~~~~~~~~~~~
    'onmessageerror' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5607:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'location' must be of type 'Location', but here has type 'WorkerLocation'.

5607 declare var location: WorkerLocation;
                 ~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17172:13
    17172 declare var location: Location;
                      ~~~~~~~~
    'location' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5609:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'navigator' must be of type 'Navigator', but here has type 'WorkerNavigator'.

5609 declare var navigator: WorkerNavigator;
                 ~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17179:13
    17179 declare var navigator: Navigator;
                      ~~~~~~~~~
    'navigator' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5610:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onerror' must be of type 'OnErrorEventHandler', but here has type '((this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any) | null'.

5610 declare var onerror: ((this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any) | null;
                 ~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17365:13
    17365 declare var onerror: OnErrorEventHandler;
                      ~~~~~~~
    'onerror' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5611:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onlanguagechange' must be of type '((this: Window, ev: Event) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null'.

5611 declare var onlanguagechange: ((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null;
                 ~~~~~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17550:13
    17550 declare var onlanguagechange: ((this: Window, ev: Event) => any) | null;
                      ~~~~~~~~~~~~~~~~
    'onlanguagechange' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5612:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onoffline' must be of type '((this: Window, ev: Event) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null'.

5612 declare var onoffline: ((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null;
                 ~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17553:13
    17553 declare var onoffline: ((this: Window, ev: Event) => any) | null;
                      ~~~~~~~~~
    'onoffline' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5613:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'ononline' must be of type '((this: Window, ev: Event) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null'.

5613 declare var ononline: ((this: DedicatedWorkerGlobalScope, ev: Event) => any) | null;
                 ~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17554:13
    17554 declare var ononline: ((this: Window, ev: Event) => any) | null;
                      ~~~~~~~~
    'ononline' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5614:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onrejectionhandled' must be of type '((this: Window, ev: PromiseRejectionEvent) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null'.

5614 declare var onrejectionhandled: ((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null;
                 ~~~~~~~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17558:13
    17558 declare var onrejectionhandled: ((this: Window, ev: PromiseRejectionEvent) => any) | null;
                      ~~~~~~~~~~~~~~~~~~
    'onrejectionhandled' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5615:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'onunhandledrejection' must be of type '((this: Window, ev: PromiseRejectionEvent) => any) | null', but here has type '((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null'.

5615 declare var onunhandledrejection: ((this: DedicatedWorkerGlobalScope, ev: PromiseRejectionEvent) => any) | null;
                 ~~~~~~~~~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17560:13
    17560 declare var onunhandledrejection: ((this: Window, ev: PromiseRejectionEvent) => any) | null;
                      ~~~~~~~~~~~~~~~~~~~~
    'onunhandledrejection' was also declared here.

Error: node_modules/typescript/lib/lib.webworker.d.ts:5617:13 - error TS2403: Subsequent variable declarations must have the same type.  Variable 'self' must be of type 'Window & typeof globalThis', but here has type 'WorkerGlobalScope & typeof globalThis'.

5617 declare var self: WorkerGlobalScope & typeof globalThis;
                 ~~~~

  node_modules/typescript/lib/lib.dom.d.ts:17212:13
    17212 declare var self: Window & typeof globalThis;
                      ~~~~
    'self' was also declared here.