Pdfmake is a great library but has the downside of big code size. To be fair, the size comes from its dependencies not for its own code
Here are the strategies i used to reduce the code by half and also get rid of vfs_fonts.js
The fontkit changes were published as fontkit-lite
The pdfmake changes were published as pdfmake-lite
Let me know if any of this changes can be integrated in the project. One possibility is to create two bundles: pdfmake.js with all features, and pdfmake-lite.js with smaller bundle and a few less features.
This is the code i'm using to load the fonts on demand:
function fetchFont (fontURL) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest()
request.open('GET', fontURL, true)
request.responseType = 'arraybuffer'
request.onload = function (e) {
resolve(request.response)
}
request.onerror = reject
request.send()
})
}
class PdfFontLoader {
constructor () {
this.fontDefs = []
this.vfs = {}
}
addFont (fontDef) {
this.fontDefs.push(fontDef)
}
load () {
return new Promise((resolve, reject) => {
if (this.loaded) {
resolve()
} else {
const fetches = this.fontDefs.map(fontDef => {
return fetchFont(fontDef.URL).then((data) => {
this.vfs[fontDef.name] = data
})
})
Promise.all(fetches).then(() => {
this.loaded = true
resolve()
}).catch(reject)
}
})
}
}
export const fontLoader = new PdfFontLoader()
pdfMake.vfs = fontLoader.vfs
fontLoader.addFont({URL: 'Roboto-Regular.ttf', name: 'Roboto-Regular.ttf'})
fontLoader.addFont({URL: 'Roboto-Italic.ttf', name: 'Roboto-Italic.ttf'})
fontLoader.addFont({URL: 'Roboto-Medium.ttf', name: 'Roboto-Medium.ttf'})
fontLoader.addFont({URL: 'Roboto-MediumItalic.ttf', name: 'Roboto-MediumItalic.ttf'})
//later call fontLoader.load()
Awesome stuff @blikblum ! Just started using pdfmake and had been looking to bring down the bundle size of my app, so this has been super helpful! pdfmake-lite is working well so far 👍
Regarding fonts, I had a question. I'm trying to see if I could get avoid using vfs_fonts.js by using fontkit-lite.
Where do the font files come from in your example?
fontLoader.addFont({URL: 'Roboto-Regular.ttf', name: 'Roboto-Regular.ttf'})
fontLoader.addFont({URL: 'Roboto-Italic.ttf', name: 'Roboto-Italic.ttf'})
fontLoader.addFont({URL: 'Roboto-Medium.ttf', name: 'Roboto-Medium.ttf'})
fontLoader.addFont({URL: 'Roboto-MediumItalic.ttf', name: 'Roboto-MediumItalic.ttf'})
Somewhere in _node_modules_? I looked in fontkit-lite but didn't seem them.
Thanks!
The font files are in the same server, deployed with the app bundle.
I wrote a library to load assets dynamically. https://github.com/blikblum/pdfmake-utils
And a full example at https://github.com/blikblum/pdfmake-playground
Thanks @blikblum !
I ended up pulling them down and bundling them with webpack from here
https://github.com/google/fonts#download-all-google-fonts
Thanks for all your help, it looks like with this I was able to get the pdfmake bundle size down from 2.53 MB to 1.18 MB (uncompressed) 🎉
@blikblum This simply cannot be realized because:
Now only iconv-lite can be removed on "lite" package, but it doesn't bring a big size reduction without others (fontkit/pdfkit).
@liborm85 All fine
I know the limitations of fontkit. That's i i'm maintaining my fork (without IndicShaper and Woff2Font); Hopefully we can make it more modular;
iconv-lite is 125k minified which alone is bigger than react: https://bundlephobia.com/[email protected]. Fonts that don't have cmap are rare these days
Regarding font loading, it could be added a recipe how to do it. Webpack users can have a great benefit since sometimes the font is already loaded by the browser to use in the webpage
BTW: in my pdfmake-lite package i use vanilla / unchanged pdfkit. The only thing that can be improved size wise in pdfkit is making the password support optional
Is it possible to use fonts in vfs_fonts.js in your CSS for general styling to avoid having to load them twice?
It is possible but i never got time to do a test.
We did it with async javascript. We were loading fonts when there was a
need to create a pdf.
On Mon, Jun 8, 2020 at 7:10 PM Luiz Américo notifications@github.com
wrote:
It is possible but i never got time to do a test.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/bpampuch/pdfmake/issues/1374#issuecomment-640609547,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AF6MDNIXVNUYIVMJ4EC33L3RVTS3NANCNFSM4FASUU3A
.
Fetching fonts in project from url address solves version 0.1.66+. Usage is described documentation.
What about the typings for pdfmake-lite? I just installed it on my Angular App and seems to be a good way to reduce the bundle size (was 2.3 MB based on analyzer, now it is 1.62 MB)
Most helpful comment
The font files are in the same server, deployed with the app bundle.
I wrote a library to load assets dynamically. https://github.com/blikblum/pdfmake-utils
And a full example at https://github.com/blikblum/pdfmake-playground