This is my first article on Medium. Having gained a lot of knowledge on medium, I thought its my responsibility too to help out others with the things that I have learned, one of it being this annoying and quite tedious topic of generating PDF with electron.js.

TL;DR : Skip to last section where I have written example code for PDF generation.

If you’re new to electron and want to start using react with it, there is a github repo for all awesome react stuffs with electron. https://github.com/ishwarrimal/electron-with-react

I am going to share my story on all the approaches I have used to solve this problem and finally the best solution that I found.

(This is not a tutorial for absolute beginner, instead it’s for developers who have tried doing it and were unsuccessful. I have assumed that you know basics of electeon.js)

2 years back in November of 2016, I started my journey with electron.js in a startup where I was hired to develop a desktop app (for their existing mobile app)with just knowledge on JavaScript and basics of node.js. Since I was the first employee there, I had very less help from anyone; and electron being relatively new, there were very less discussions on even the basic problems and doubts I encountered. The most annoying and time consuming among those problems was that of generating pdf. It was quite a tricky problem.

Back in Jan 2017,

Everything was going good, we had a nice accounting app build on electron. Having opportunity to use CSS and JavaScript, our app was quite appealing(in fact way better) to the modern users who wanted easy/beautiful UI and fast UX compared to our competitors who had traditional app which was built on .net or other frameworks with comparatively lesser flexibility of UI design to that of CSS.

Our basic app was ready for going to production, but there was one last feature required for first release(If anyone wants help regarding auto updating of app please let me know in comments). And it was that of generating PDF. So like everyone else, I opened google and searched this ‘generating pdf with electron.js

I was happy that there was an existing tool electron-pdf to help me with this. I made use of it in our app, surprisingly it was quite simple to generate pdf. It was working all fine. I achieved my goal in lesser time then expected.

Final test was performed in development, we could generate PDF with so much ease, electonr-pdf was working like charm. We were all set to generate the app for production.

For security reason, we had to make use of ‘asar’ to compress our files in production which makes our code quite tough to un-compress by users and read/alter the code(though, anyone with common sense and who knows to search in google can easily un-compress it).

The app for production was ready, launched the installer and opened the app for testing and…. it failed to generate pdf. There were some error. I tried building again thinking (and hoping) that maybe I did some mistake while building package. But nope, again and again same problem. The error:

Uncaught Error: write EPIPE
at exports._errnoException (util.js:1022)
at Socket._writeGeneric (net.js:715)
at Socket._write (net.js:734)
at doWrite (_stream_writable.js:332)
at writeOrBuffer (_stream_writable.js:318)
at Socket.Writable.write (_stream_writable.js:245)
at Socket.write (net.js:661)
at PDF.PdfExec [as exec] (C:\Project\Project-win32-ia32\resources\app.asar\node_modules\html-pdf\lib\pdf.js:136)
at PDF.PdfToFile [as toFile] (C:\Project\Project-win32-ia32\resources\app.asar\node_modules\html-pdf\lib\pdf.js:83)
at generatePdf (:1155:43)

Searched everywhere, but couldn’t find any solution. Did a bit research and finally got to know that electron-pdf does some write operation internally and the ‘asar’ what we were using to generate compressed code, does not allow any WRITE operation inside of the package(app.asar). So was out of luck with it.

I did a bit of experiment of installing the package of electron-pdf and its dependencies elsewhere and moving the package in parent folder instead of keeping it in node-modules folder. All the code were same, just instead of requiring ‘electron-pdf’ in normal node_nodules manner , it was needed to require by giving the parent directory ‘./../electron-pdf’. And it worked like intended.

so was the problem with saving client_secret key and other keys which is required by google while using their mail and drive api from within the app. It is also generated in production, so we had to create another folder in parent directory i.e. outside app.asar where we could store the generated file. If you need help on how to use google api for mail and drive let me know in comments.

After building package(ready for next step of generating installer), I placed ‘electron-pdf’ package manually in the directory along with app.asar(obvious note: node modules and all our codes will be inside the package app.asar).

Now this did the work for me. All I had to do was build package and then paste the electron-pdf module inside resource/ folder alongsinde app.asar. And then run command to generate installer for distribution. Installer generated, installed it in local machine and it was working all fine. Was able to generate pdf. But there was another problem; since we placed the package explicitly, the size of installer was huge. Previously it was around 60 MB but with implementation of this new method, size was in 90+ MBs. It was huge, but we had no other go.

Many days passed with this helpless approach, then while browsing through electron webContents page, I saw a lot of methods which I was not aware of(neglected to go through the entire page in the beginning). There I found a lot of methods which were very very useful and would have made my life a lot easier if I had gone through this before.

There was this specific method contents.printToPDF(options, callback). This method was all that I was looking for. Where contents is the reference to the browserWindow which we want to convert to pdf. So now all we had to do is, open a browserWindow with the content we wanted to print and then run the above command with the required options. You can find the details here : https://github.com/electron/electron/blob/master/docs/api/web-contents.md#contentsprinttopdfoptions-callback

Example code:

window_to_PDF = new BrowserWindow({show : false});//to just open the browser in backgroundwindow_to_PDF.loadURL('anylink.html'); //give the file link you want to displayfunction pdfSettings() {
var paperSizeArray = ["A4", "A5"];
var option = {
landscape: false,
marginsType: 0,
printBackground: false,
printSelectionOnly: false,
pageSize: paperSizeArray[settingCache.getPrintPaperSize()-1],
};
return option;
}
window_to_PDF.webContents.printToPDF(pdfSettings(), function(err, data) {
if (err) {
//do whatever you want
return;
}
try{
fs.writeFileSync('./generated_pdf.pdf', data);
}catch(err){
//unable to save pdf..
}

})

And that solved my problem. End of my story.

This solved my problem without using any external module.

Hope this helps someone. Since this is my first attempt to write article. All sort of criticisms/suggestions are accepted and I would request you to correct/guide/help me in making this article better.

If you find this article useful, you can show your appreciation by clicking on clap button. As the saying goes, ‘When we give cheerfully and accept gratefully, everyone is blessed’.

I write articles on JavaScript, electron, and react. Opted for curators for better reach, not money. Open link in incognito to read for free (or contact me)