7

Running Headless Chrome Inside Adobe Cloud Manager Builds

 3 years ago
source link: https://medium.com/adobetech/running-headless-chrome-inside-adobe-cloud-manager-builds-7e556a97dce4
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Running Headless Chrome Inside Adobe Cloud Manager Builds

Image for post
Image for post

I found myself creating critical CSS client libraries for an Adobe Experience Manager project as part of a series of performance improvements recently.

What is Critical CSS?

Historically, web site performance has been mainly focussed on server rendering and database query optimisation; but in 2020, front end performance is critical to the success of any website. SEO optimisation is no longer simply focussed on getting the right content and links in place — speed of rendering is a key metric to track and improve.

Some of these KPIs are met by prioritising the rendering of aspects of a page that the user will see first. This typically is the top part of the page, also known as “above the fold”. Since the whole stylesheet isn’t needed to display this part of the page, it is wasteful to synchronously load the whole set of rules. This is especially key, since loading CSS is a render block action, and prevents anything else happening.

Identifying the specific rules that are necessary to render the above the fold content is not a trivial task. These specific rules are known as critical CSS, and best practice is to load this small subset of rules synchronously and then load the remaining rules (non-critical) asynchronously.

Auto Generating the Critical CSS

Fortunately, browsers are pretty good at working out which rules are critical, and the Penthouse npm module can be incorporated into build processes.

The problem is that the underlying technology, Puppeteer uses headless Chromium to generate the critical CSS, which was running just fine locally as part of the Maven project build, and on the self managed Jenkins instance, but was failing inside the Adobe Cloud Manager build environment:

[emitted]         (node:2509) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
10:36:24,006 [Exec Stream Pumper] [INFO] /build_root/build/project/ui.frontend/src/main/frontend/node_modules/puppeteer/.local-chromium/linux-722234/chrome-linux/chrome: error while loading shared libraries: libX11-xcb.so.1: cannot open shared object file: No such file or directory

This was because the build environment was lacking the dependencies for the local chromium install to run.

Fortunately, Adobe Cloud Manager allows additional system dependencies to be installed, and adding a specific profile to install these dependencies in the maven pom file, resolved the issue:

<profile>
<id>cmBuild</id>
<activation>
<property>
<name>env.CM_BUILD</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>apt-get-update</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>apt-get</executable>
<arguments>
<argument>update</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>install-puppeteer-dependencies</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>apt-get</executable>
<arguments>
<argument>install</argument>
<argument>-y</argument>
<argument>--no-install-recommends</argument>
<argument>gconf-service</argument>
<argument>libxext6</argument>
<argument>libxfixes3</argument>
<argument>libxi6</argument>
<argument>libxrandr2</argument>
<argument>libxrender1</argument>
<argument>libcairo2</argument>
<argument>libcups2</argument>
<argument>libdbus-1-3</argument>
<argument>libexpat1</argument>
<argument>libfontconfig1</argument>
<argument>libgcc1</argument>
<argument>libgconf-2-4</argument>
<argument>libgdk-pixbuf2.0-0</argument>
<argument>libglib2.0-0</argument>
<argument>libgtk-3-0</argument>
<argument>libnspr4</argument>
<argument>libpango-1.0-0</argument>
<argument>libpangocairo-1.0-0</argument>
<argument>libstdc++6</argument>
<argument>libx11-6</argument>
<argument>libx11-xcb1</argument>
<argument>libxcb1</argument>
<argument>libxcomposite1</argument>
<argument>libxcursor1</argument>
<argument>libxdamage1</argument>
<argument>libxss1</argument>
<argument>libxtst6</argument>
<argument>libappindicator1</argument>
<argument>libnss3</argument>
<argument>libasound2</argument>
<argument>libatk1.0-0</argument>
<argument>libc6</argument>
<argument>ca-certificates</argument>
<argument>fonts-liberation</argument>
<argument>lsb-release</argument>
<argument>xdg-utils</argument>
<argument>wget</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>

This uses the exec-maven-plugin to execute shell commands, in this case the apt-get package manager command, to install additional system packages to allow the headless Chromium instance to run.

The profile is activated using the CM_BUILD environment variable, which ensures it will only run this profile as part of Cloud Manager build.

What Other Uses Cases?

Since, this technique is simply a means by which you can get additional system packages installed on your Cloud Manager build instance, the sky is the limit for this.

Perhaps you have Selenium based integration tests that need a headless Chrome instance to run.

Perhaps you need to generate test data or dispatcher configuration with Perl or Python scripts.

Try it out, and see what you can imagine.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK