chrome-aws-lambda
chrome-aws-lambda copied to clipboard
fonts.conf file doesn't seem to be read when trying to disable anti-aliasing and font hinting
Hi! I'm completely new to the serverless world and I'm trying to set up correctly my first lambda with puppeteer. Everything is working as expected. Kudos for this repo and how you maintain it 🙏 .
My issue is that I'm trying to disable all (system wide) fonts options: anti-aliasing
, hinting
, etc. with a fonts.conf
file but it doesn't seem to work. My goal is to have a "pixel-perfect" screenshot.
I'm using the latest layer for my runtime (nodejs12.x) provided by shelfio, like that:
provider:
name: aws
layers:
# https://github.com/shelfio/chrome-aws-lambda-layer
- arn:aws:lambda:${self:provider.region}:764866452798:layer:chrome-aws-lambda:20
# function parameters
runtime: nodejs12.x
[...]
functions:
run:
handler: handler.run
environment:
FONTCONFIG_PATH: /var/task/fonts
And I've added a specific directory fonts
in the lambda root code containing:
- a font
Verdana.ttf
- a
fonts.conf
file:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/var/task/fonts/</dir>
<match target="font">
<edit name="rgba" mode="assign"><const>rgb</const></edit>
<edit name="hinting" mode="assign"><bool>false</bool></edit>
<edit name="antialias" mode="assign"><bool>false</bool></edit>
<edit name="autohint" mode="assign"><bool>false</bool></edit>
<edit name="hintstyle" mode="assign"><const>hintnone</const></edit>
<edit name="lcdfilter" mode="assign"><const>lcdnone</const></edit>
</match>
<config></config>
</fontconfig>
Plus, I've added the FONTCONFIG_PATH: /var/task/fonts
env var in the serverless.yml
file.
Verdana font is working well 👍 . But the screenshot still appear blurry. I've tested locally with the same fonts.conf
file in Docker, and the screenshot is perfect, like I want.
The browser is instantiated like that:
const chromium = require('chrome-aws-lambda');
[...]
const browser = await chromium.puppeteer.launch({
args: chromium.args,
executablePath: await chromium.executablePath,
defaultViewport: { width: 400, height: 300 },
});
Do you have any clue on why my fonts.conf
is "partially read"? Or maybe something is overriding it in the runtime context of a lambda? Thanks!
EDIT: Oops, wrong tag. It's question
not enhancement
. Sorry
Hello, it's me again!
I've just found what was causing my issue. 🤩
I first thought it was a fontconfig path issue, because the layer lives in /opt/nodejs
or maybe it was a missing lib as you have compiled a lighter chromium. But not at all.
As we can see in my previous post, I'm calling puppeteer this way:
const chromium = require('chrome-aws-lambda');
[...]
const browser = await chromium.puppeteer.launch({
args: chromium.args,
executablePath: await chromium.executablePath,
defaultViewport: { width: 400, height: 300 },
});
If we look for what are these args
we can found the list in https://github.com/alixaxel/chrome-aws-lambda/blob/master/source/index.js#L83. I've tested each one separately.
And the culprit is:
if (this.headless === true) {
result.push('--single-process');
}
I don't really understand the relation between this --single-process
chromium flag and my fonts.conf
not being respected, neither if this flag is really required here. But for now, I will just pass my own custom set of flags instead of calling the default one (args: chromium.args
).
Thanks!
Update. Even if it works well locally with a lambci/lambda:nodejs12.x
Docker image from shelf.io. In real AWS environment the lambda timeout on const page = await browser.newPage();
when I remove the --single-process
flag.
Back to square one 😕
I too am stuck on this and the fonts I add are not being used/added in AWS runtime. Works fine locally using localstack but running the same in Lambda on AWS gives (what looks like) Open Sans
even though font-face in CSS is Arial, Tahoma, Verdana
but I've tried a bunch of different ones.
Ok, a little progress... I did "force" it to use the /var/task/fonts
path for fonts by changing this in source/index.js
and the rebuilding:
if (['AWS_Lambda_nodejs10.x', 'AWS_Lambda_nodejs12.x'].includes(process.env.AWS_EXECUTION_ENV) === true) {
//if (process.env.FONTCONFIG_PATH === undefined) {
process.env.FONTCONFIG_PATH = '/var/task/fonts';
//}
if (process.env.LD_LIBRARY_PATH === undefined) {
process.env.LD_LIBRARY_PATH = '/tmp/aws/lib';
} else if (process.env.LD_LIBRARY_PATH.startsWith('/tmp/aws/lib') !== true) {
process.env.LD_LIBRARY_PATH = [...new Set(['/tmp/aws/lib', ...process.env.LD_LIBRARY_PATH.split(':')])].join(':');
}
}
And of cource added a fonts
directory with a fonts.conf
like:
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
<dir>/var/task/fonts/</dir>
<cachedir>/tmp/fonts-cache/</cachedir>
<alias>
<family>Arial</family>
<default>
<family>DejaVu Sans</family>
</default>
</alias>
<match target="font" >
<edit mode="assign" name="autohint"> <bool>false</bool></edit>
<edit mode="assign" name="hinting"> <bool>true</bool></edit>
<edit mode="assign" name="hintstyle"> <const>hintfull</const></edit>
<edit mode="assign" name="antialias"> <bool>true</bool></edit>
<edit mode="assign" name="rgba"> <const>rgb</const></edit>
<edit mode="assign" name="lcdfilter"> <const>lcdlight</const></edit>
</match>
<!-- smaller than 9px -->
<match target="font">
<test name="pixelsize" qual="any" compare="less"><double>9</double></test>
<edit mode="assign" name="antialias"> <bool>false</bool></edit>
</match>
<!-- the below are noops for now -->
<!-- bigger than 15px -->
<match target="font">
<test name="pixelsize" qual="any" compare="more"><double>15</double></test>
<edit mode="assign" name="hintstyle"><const>hintfull</const></edit>
<edit mode="assign" name="lcdfilter"><const>lcdlight</const></edit>
</match>
<!-- Bold fonts -->
<match target="font">
<test name="weight" compare="more"><const>medium</const></test>
<edit mode="assign" name="hintstyle"><const>hintfull</const></edit>
<edit mode="assign" name="lcdfilter"><const>lcdlight</const></edit>
</match>
<!-- Italic fonts -->
<match target="font">
<test name="slant" compare="not_eq"><double>0</double></test>
<edit mode="assign" name="hintstyle"><const>hintfull</const></edit>
<edit mode="assign" name="lcdfilter"><const>lcdlight</const></edit>
</match>
</fontconfig>
@QAnders does it load the font config for you? I have the same setup as @qboot and loading fonts from the fonts folder works fine. But the settings of the fonts.conf file are never applied.
@alixaxel I can confirm that the 7.0.0 version fixes that problem! So this can be closed.