Skip to content

Commit 8a8f357

Browse files
committed
feat(driver): bundle playwright-core in driver, keep only Node.js in driver-bundle
Move the platform-independent playwright-core package and the DriverJar loader from driver-bundle into the always-present driver module. driver-bundle now contains only the Node.js binaries, one per platform. DriverJar assembles the driver directory from two classpath roots: the shared package (driver module) and the host platform's Node.js (driver-bundle), the latter skipped when a preinstalled Node.js is configured. This lets a user with a preinstalled Node.js (PLAYWRIGHT_NODEJS_PATH) exclude the driver-bundle dependency entirely.
1 parent ace7a12 commit 8a8f357

8 files changed

Lines changed: 80 additions & 55 deletions

File tree

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ git clone https://github.com/microsoft/playwright-java
2020
cd playwright-java
2121
```
2222

23-
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).
23+
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).
2424

2525
```bash
2626
scripts/download_driver.sh

driver-bundle/pom.xml

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,17 @@
1010
</parent>
1111

1212
<artifactId>driver-bundle</artifactId>
13-
<name>Playwright - Drivers For All Platforms</name>
13+
<name>Playwright - Node.js For All Platforms</name>
1414
<description>
15-
This module includes Playwright driver and related utilities for all supported platforms.
16-
It is intended to be used on the systems where Playwright driver is not preinstalled.
15+
This module bundles the Node.js binaries needed to run the Playwright driver on every supported
16+
platform. The platform-independent driver code lives in the driver module. It is intended for
17+
systems where Node.js is not preinstalled; when Node.js is available on the host (see the
18+
PLAYWRIGHT_NODEJS_PATH environment variable) this dependency can be excluded.
1719
</description>
1820

19-
<dependencies>
20-
<dependency>
21-
<groupId>com.microsoft.playwright</groupId>
22-
<artifactId>driver</artifactId>
23-
<version>${project.version}</version>
24-
<scope>compile</scope>
25-
</dependency>
26-
<dependency>
27-
<groupId>org.junit.jupiter</groupId>
28-
<artifactId>junit-jupiter-engine</artifactId>
29-
</dependency>
30-
</dependencies>
31-
3221
<build>
3322
<plugins>
34-
<!-- The driver binaries for all platforms live in src/main/resources and must not
23+
<!-- The Node.js binaries for all platforms live in src/main/resources and must not
3524
be packaged into the sources JAR (see issue #1913). -->
3625
<plugin>
3726
<groupId>org.apache.maven.plugins</groupId>

driver/pom.xml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
<artifactId>driver</artifactId>
1313
<name>Playwright - Driver</name>
1414
<description>
15-
This module provides API for discovery and launching of Playwright driver.
15+
This module provides the API for discovery and launching of the Playwright driver. It also
16+
bundles the platform-independent driver code (the playwright-core package); the matching
17+
Node.js binary is provided by the driver-bundle module or by a preinstalled Node.js.
1618
</description>
1719

1820
<dependencies>
@@ -21,4 +23,18 @@
2123
<artifactId>junit-jupiter-engine</artifactId>
2224
</dependency>
2325
</dependencies>
26+
27+
<build>
28+
<plugins>
29+
<!-- The playwright-core package lives in src/main/resources and must not be packaged
30+
into the sources JAR (see issue #1913). -->
31+
<plugin>
32+
<groupId>org.apache.maven.plugins</groupId>
33+
<artifactId>maven-source-plugin</artifactId>
34+
<configuration>
35+
<excludeResources>true</excludeResources>
36+
</configuration>
37+
</plugin>
38+
</plugins>
39+
</build>
2440
</project>

driver/src/main/java/com/microsoft/playwright/impl/driver/Driver.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525

2626
/**
2727
* This class provides access to playwright-cli. It can be either preinstalled
28-
* in the host system and its path is passed as a system property or it can be
29-
* loaded from the driver-bundle module if that module is in the classpath.
28+
* in the host system and its path is passed as a system property, or it can be
29+
* loaded from the classpath: the platform-independent driver code ships in the
30+
* driver module and the Node.js binary in the optional driver-bundle module.
3031
*/
3132
public abstract class Driver {
3233
protected final Map<String, String> env = new LinkedHashMap<>(System.getenv());

driver-bundle/src/main/java/com/microsoft/playwright/impl/driver/jar/DriverJar.java renamed to driver/src/main/java/com/microsoft/playwright/impl/driver/jar/DriverJar.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,26 @@ public static URI getDriverResourceURI() throws URISyntaxException {
119119
}
120120

121121
void extractDriverToTempDir() throws URISyntaxException, IOException {
122-
URI originalUri = getDriverResourceURI();
122+
// The platform-independent driver code (the playwright-core package) ships in the driver
123+
// module and is always on the classpath.
124+
extractResourceToDir("driver/package", driverTempDir.resolve("package"));
125+
// The Node.js binary is only needed when it is not preinstalled on the host. It ships in the
126+
// optional driver-bundle module, one binary per platform; a user with a preinstalled Node.js
127+
// can exclude that dependency entirely.
128+
if (preinstalledNodePath == null) {
129+
String platformResource = "driver/" + platformDir();
130+
if (DriverJar.class.getClassLoader().getResource(platformResource) == null) {
131+
throw new RuntimeException("Failed to find the bundled Node.js for platform '" + platformDir()
132+
+ "'. Add the com.microsoft.playwright:driver-bundle dependency, or set the "
133+
+ PLAYWRIGHT_NODEJS_PATH + " environment variable (or the playwright.nodejs.path system "
134+
+ "property) to point at a preinstalled Node.js.");
135+
}
136+
extractResourceToDir(platformResource, driverTempDir);
137+
}
138+
}
139+
140+
private void extractResourceToDir(String resourcePath, Path destDir) throws URISyntaxException, IOException {
141+
URI originalUri = DriverJar.class.getClassLoader().getResource(resourcePath).toURI();
123142
URI uri = maybeExtractNestedJar(originalUri);
124143

125144
// Create zip filesystem if loading from jar.
@@ -131,14 +150,8 @@ void extractDriverToTempDir() throws URISyntaxException, IOException {
131150
// See https://github.com/microsoft/playwright-java/issues/306
132151
Path srcRootDefaultFs = Paths.get(srcRoot.toString());
133152
Files.walk(srcRoot).forEach(fromPath -> {
134-
if (preinstalledNodePath != null) {
135-
String fileName = fromPath.getFileName().toString();
136-
if ("node.exe".equals(fileName) || "node".equals(fileName)) {
137-
return;
138-
}
139-
}
140153
Path relative = srcRootDefaultFs.relativize(Paths.get(fromPath.toString()));
141-
Path toPath = driverTempDir.resolve(relative.toString());
154+
Path toPath = destDir.resolve(relative.toString());
142155
try {
143156
if (Files.isDirectory(fromPath)) {
144157
Files.createDirectories(toPath);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
driver/
2+
local-driver/

driver-bundle/src/test/java/com/microsoft/playwright/impl/driver/jar/TestInstall.java renamed to playwright/src/test/java/com/microsoft/playwright/impl/driver/jar/TestInstall.java

File renamed without changes.

scripts/download_driver.sh

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ cd "$(dirname $0)"
99
if [[ ($1 == '-h') || ($1 == '--help') ]]; then
1010
echo ""
1111
echo "This script downloads and assembles the Playwright driver for all platforms."
12-
echo "Each driver is assembled from the 'playwright-core' npm package and the matching"
13-
echo "Node.js binary from https://nodejs.org, the same way the upstream Playwright build"
14-
echo "does it. The result is put under 'driver-bundle/src/main/resources/driver'."
12+
echo "The platform-independent 'playwright-core' npm package is assembled once into the driver"
13+
echo "module ('driver/src/main/resources/driver/package'), and the matching Node.js binary from"
14+
echo "https://nodejs.org for each platform goes into the driver-bundle module"
15+
echo "('driver-bundle/src/main/resources/driver/<platform>'), the same way the upstream"
16+
echo "Playwright build does it."
1517
echo ""
1618
echo "Usage: scripts/download_driver.sh [option]"
1719
echo ""
@@ -56,20 +58,25 @@ echo "Driver version: $DRIVER_VERSION"
5658
echo "Upstream commit: $GIT_HEAD"
5759
echo "Node.js version: $NODE_VERSION"
5860

59-
cd ../driver-bundle/src/main/resources
61+
# The platform-independent driver code (playwright-core) is assembled once into the driver module;
62+
# the Node.js binary for each platform is assembled into the driver-bundle module. See issue #1196.
63+
ROOT="$(cd .. && pwd)"
64+
CORE_DEST="$ROOT/driver/src/main/resources/driver"
65+
NODE_DEST="$ROOT/driver-bundle/src/main/resources/driver"
6066

61-
if [[ -d 'driver' ]]; then
62-
echo "Deleting existing drivers from $(pwd)"
63-
rm -rf driver
64-
fi
65-
66-
mkdir -p driver
67-
cd driver
67+
TMP_DIR="$(mktemp -d)"
68+
trap 'rm -rf "$TMP_DIR"' EXIT
6869

69-
# Download the platform-independent driver package (playwright-core) once.
70-
CORE_TGZ="$(pwd)/playwright-core-$DRIVER_VERSION.tgz"
70+
# 1. playwright-core package -> driver module (once, shared by every platform).
71+
echo "Assembling playwright-core package to $CORE_DEST/package"
72+
rm -rf "$CORE_DEST/package"
73+
mkdir -p "$CORE_DEST"
74+
CORE_TGZ="$TMP_DIR/playwright-core-$DRIVER_VERSION.tgz"
7175
download "https://registry.npmjs.org/playwright-core/-/playwright-core-$DRIVER_VERSION.tgz" "$CORE_TGZ"
76+
# The npm tarball has a top-level package/ directory, so this creates $CORE_DEST/package.
77+
tar -xzf "$CORE_TGZ" -C "$CORE_DEST"
7278

79+
# 2. Node.js binary for each platform -> driver-bundle module.
7380
# <java platform dir>:<nodejs platform suffix>:<archive extension>
7481
for ENTRY in \
7582
"mac:darwin-x64:tar.gz" \
@@ -79,28 +86,25 @@ for ENTRY in \
7986
"win32_x64:win-x64:zip"
8087
do
8188
IFS=':' read -r PLATFORM NODE_SUFFIX ARCHIVE <<< "$ENTRY"
82-
echo "Assembling driver for $PLATFORM to $(pwd)/$PLATFORM"
83-
mkdir "$PLATFORM"
89+
DEST="$NODE_DEST/$PLATFORM"
90+
echo "Assembling Node.js for $PLATFORM to $DEST"
91+
rm -rf "$DEST"
92+
mkdir -p "$DEST"
8493

85-
# 1. playwright-core package contents -> $PLATFORM/package
86-
tar -xzf "$CORE_TGZ" -C "$PLATFORM"
87-
88-
# 2. Node.js binary and its license from the official Node.js distribution.
94+
# Node.js binary and its license from the official Node.js distribution.
8995
NODE_DIR="node-v$NODE_VERSION-$NODE_SUFFIX"
90-
NODE_ARCHIVE="$NODE_DIR.$ARCHIVE"
96+
NODE_ARCHIVE="$TMP_DIR/$NODE_DIR.$ARCHIVE"
9197
download "https://nodejs.org/dist/v$NODE_VERSION/$NODE_DIR.$ARCHIVE" "$NODE_ARCHIVE"
9298
if [[ $ARCHIVE == "zip" ]]; then
93-
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$PLATFORM"
94-
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$PLATFORM"
99+
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/node.exe" -d "$DEST"
100+
unzip -joq "$NODE_ARCHIVE" "$NODE_DIR/LICENSE" -d "$DEST"
95101
else
96-
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=2 "$NODE_DIR/bin/node"
97-
tar -xzf "$NODE_ARCHIVE" -C "$PLATFORM" --strip-components=1 "$NODE_DIR/LICENSE"
102+
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=2 "$NODE_DIR/bin/node"
103+
tar -xzf "$NODE_ARCHIVE" -C "$DEST" --strip-components=1 "$NODE_DIR/LICENSE"
98104
fi
99105
rm -f "$NODE_ARCHIVE"
100106
done
101107

102-
rm -f "$CORE_TGZ"
103-
104108
echo ""
105109
echo "All drivers have been successfully assembled."
106110
echo ""

0 commit comments

Comments
 (0)