1
0
mirror of synced 2026-07-07 09:00:02 +00:00

feat(driver): bundle playwright-core in driver, keep only Node.js in driver-bundle (#1936)

This commit is contained in:
Yury Semikhatsky
2026-06-19 09:54:36 -07:00
committed by GitHub
parent 43d2601be8
commit d2d29d446d
9 changed files with 73 additions and 56 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ git clone https://github.com/microsoft/playwright-java
cd playwright-java
```
2. Run the following script to download and assemble the Playwright driver for all platforms into `driver-bundle/src/main/resources/driver/` directory (browser binaries for Chromium, Firefox and WebKit will be automatically downloaded later on first Playwright run).
2. Run the following script to download and assemble the Playwright driver. The platform-independent `playwright-core` package is assembled once into `driver/src/main/resources/driver/package/`, and the Node.js binary for each platform into `driver-bundle/src/main/resources/driver/<platform>/` (browser binaries for Chromium, Firefox and WebKit will be automatically downloaded later on first Playwright run).
```bash
scripts/download_driver.sh
+4 -17
View File
@@ -10,28 +10,15 @@
</parent>
<artifactId>driver-bundle</artifactId>
<name>Playwright - Drivers For All Platforms</name>
<name>Playwright - Node.js For All Platforms</name>
<description>
This module includes Playwright driver and related utilities for all supported platforms.
It is intended to be used on the systems where Playwright driver is not preinstalled.
Node.js binaries for the Playwright driver on every supported platform. Can be excluded when
Node.js is preinstalled on the host (see PLAYWRIGHT_NODEJS_PATH).
</description>
<dependencies>
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>driver</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- The driver binaries for all platforms live in src/main/resources and must not
<!-- The Node.js binaries for all platforms live in src/main/resources and must not
be packaged into the sources JAR (see issue #1913). -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+16 -1
View File
@@ -12,7 +12,8 @@
<artifactId>driver</artifactId>
<name>Playwright - Driver</name>
<description>
This module provides API for discovery and launching of Playwright driver.
API for launching the Playwright driver. Bundles the platform-independent playwright-core
package; the Node.js binary comes from the driver-bundle module or a preinstalled Node.js.
</description>
<dependencies>
@@ -21,4 +22,18 @@
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- The playwright-core package lives in src/main/resources and must not be packaged
into the sources JAR (see issue #1913). -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<configuration>
<excludeResources>true</excludeResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -25,8 +25,9 @@ import static com.microsoft.playwright.impl.driver.DriverLogging.logWithTimestam
/**
* This class provides access to playwright-cli. It can be either preinstalled
* in the host system and its path is passed as a system property or it can be
* loaded from the driver-bundle module if that module is in the classpath.
* in the host system and its path is passed as a system property, or it can be
* loaded from the classpath: the platform-independent driver code ships in the
* driver module and the Node.js binary in the optional driver-bundle module.
*/
public abstract class Driver {
protected final Map<String, String> env = new LinkedHashMap<>(System.getenv());
@@ -119,7 +119,21 @@ public class DriverJar extends Driver {
}
void extractDriverToTempDir() throws URISyntaxException, IOException {
URI originalUri = getDriverResourceURI();
extractResourceToDir("driver/package", driverTempDir.resolve("package"));
if (preinstalledNodePath == null) {
String platformResource = "driver/" + platformDir();
if (DriverJar.class.getClassLoader().getResource(platformResource) == null) {
throw new RuntimeException("Failed to find the bundled Node.js for platform '" + platformDir()
+ "'. Add the com.microsoft.playwright:driver-bundle dependency, or set the "
+ PLAYWRIGHT_NODEJS_PATH + " environment variable (or the playwright.nodejs.path system "
+ "property) to point at a preinstalled Node.js.");
}
extractResourceToDir(platformResource, driverTempDir);
}
}
private void extractResourceToDir(String resourcePath, Path destDir) throws URISyntaxException, IOException {
URI originalUri = DriverJar.class.getClassLoader().getResource(resourcePath).toURI();
URI uri = maybeExtractNestedJar(originalUri);
// Create zip filesystem if loading from jar.
@@ -131,14 +145,8 @@ public class DriverJar extends Driver {
// See https://github.com/microsoft/playwright-java/issues/306
Path srcRootDefaultFs = Paths.get(srcRoot.toString());
Files.walk(srcRoot).forEach(fromPath -> {
if (preinstalledNodePath != null) {
String fileName = fromPath.getFileName().toString();
if ("node.exe".equals(fileName) || "node".equals(fileName)) {
return;
}
}
Path relative = srcRootDefaultFs.relativize(Paths.get(fromPath.toString()));
Path toPath = driverTempDir.resolve(relative.toString());
Path toPath = destDir.resolve(relative.toString());
try {
if (Files.isDirectory(fromPath)) {
Files.createDirectories(toPath);
+2
View File
@@ -0,0 +1,2 @@
driver/
local-driver/
+31 -26
View File
@@ -9,9 +9,11 @@ cd "$(dirname $0)"
if [[ ($1 == '-h') || ($1 == '--help') ]]; then
echo ""
echo "This script downloads and assembles the Playwright driver for all platforms."
echo "Each driver is assembled from the 'playwright-core' npm package and the matching"
echo "Node.js binary from https://nodejs.org, the same way the upstream Playwright build"
echo "does it. The result is put under 'driver-bundle/src/main/resources/driver'."
echo "The platform-independent 'playwright-core' npm package is assembled once into the driver"
echo "module ('driver/src/main/resources/driver/package'), and the matching Node.js binary from"
echo "https://nodejs.org for each platform goes into the driver-bundle module"
echo "('driver-bundle/src/main/resources/driver/<platform>'), the same way the upstream"
echo "Playwright build does it."
echo ""
echo "Usage: scripts/download_driver.sh [option]"
echo ""
@@ -56,20 +58,26 @@ echo "Driver version: $DRIVER_VERSION"
echo "Upstream commit: $GIT_HEAD"
echo "Node.js version: $NODE_VERSION"
cd ../driver-bundle/src/main/resources
# The platform-independent driver code (playwright-core) is assembled once into the driver module;
# the Node.js binary for each platform is assembled into the driver-bundle module. See issue #1196.
ROOT="$(cd .. && pwd)"
CORE_DEST="$ROOT/driver/src/main/resources/driver"
NODE_DEST="$ROOT/driver-bundle/src/main/resources/driver"
if [[ -d 'driver' ]]; then
echo "Deleting existing drivers from $(pwd)"
rm -rf driver
fi
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
mkdir -p driver
cd driver
# Download the platform-independent driver package (playwright-core) once.
CORE_TGZ="$(pwd)/playwright-core-$DRIVER_VERSION.tgz"
# 1. playwright-core package -> driver module (once, shared by every platform).
echo "Assembling playwright-core package to $CORE_DEST/package"
rm -rf "$CORE_DEST/package"
mkdir -p "$CORE_DEST"
CORE_TGZ="$TMP_DIR/playwright-core-$DRIVER_VERSION.tgz"
download "https://registry.npmjs.org/playwright-core/-/playwright-core-$DRIVER_VERSION.tgz" "$CORE_TGZ"
# The npm tarball has a top-level package/ directory, so this creates $CORE_DEST/package.
tar -xzf "$CORE_TGZ" -C "$CORE_DEST"
rm -f "$CORE_TGZ"
# 2. Node.js binary for each platform -> driver-bundle module.
# <java platform dir>:<nodejs platform suffix>:<archive extension>
for ENTRY in \
"mac:darwin-x64:tar.gz" \
@@ -79,28 +87,25 @@ for ENTRY in \
"win32_x64:win-x64:zip"
do
IFS=':' read -r PLATFORM NODE_SUFFIX ARCHIVE <<< "$ENTRY"
echo "Assembling driver for $PLATFORM to $(pwd)/$PLATFORM"
mkdir "$PLATFORM"
DEST="$NODE_DEST/$PLATFORM"
echo "Assembling Node.js for $PLATFORM to $DEST"
rm -rf "$DEST"
mkdir -p "$DEST"
# 1. playwright-core package contents -> $PLATFORM/package
tar -xzf "$CORE_TGZ" -C "$PLATFORM"
# 2. Node.js binary and its license from the official Node.js distribution.
# Node.js binary and its license from the official Node.js distribution.
NODE_DIR="node-v$NODE_VERSION-$NODE_SUFFIX"
NODE_ARCHIVE="$NODE_DIR.$ARCHIVE"
NODE_ARCHIVE="$TMP_DIR/$NODE_DIR.$ARCHIVE"
download "https://nodejs.org/dist/v$NODE_VERSION/$NODE_DIR.$ARCHIVE" "$NODE_ARCHIVE"
if [[ $ARCHIVE == "zip" ]]; then
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$PLATFORM"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$PLATFORM"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$DEST"
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$DEST"
else
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=2 "$NODE_DIR/bin/node"
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=1 "$NODE_DIR/LICENSE"
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=2 "$NODE_DIR/bin/node"
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=1 "$NODE_DIR/LICENSE"
fi
rm -f "$NODE_ARCHIVE"
done
rm -f "$CORE_TGZ"
echo ""
echo "All drivers have been successfully assembled."
echo ""
@@ -10,7 +10,6 @@ cd "$(dirname $0)"
PROJECT_DIR=$(mktemp -d)
echo "Creating project in $PROJECT_DIR"
cp -R . $PROJECT_DIR
cp -R ../../driver-bundle/src/test/ $PROJECT_DIR/src/
cp -R ../../playwright/src/test/ $PROJECT_DIR/src/
cd $PROJECT_DIR