rip out tauri bundle (v2), swc -> esbuild, blacksmith -> warpbuild, FAST CI 🚀 (#5328)

- inline mac, windows, linux bundling in the cli
- remove tauri bundle from our dep tree
- trim down the rpm crate for fewer dependencies in tree
- migrate from blacksmith to warpbuild
- move off swc and instead use esbuild via tool
- use dev drives in windows CI
- use fork of nix action for faster caching
- test bundling in CI
- fix asset handling in linux 
- add default APPDATA location for webview2 installs for dioxus apps on windows
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2026-03-20 12:27:13 -07:00
1 parent be7296f4f0
commit b2d01e6779
83 files changed
+7756 -5403

No files matched your search

+84 -223
View File
@@ -1,251 +1,112 @@
// @ts-check
const { defineConfig, devices } = require("@playwright/test");
const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
// Copy a directory to a temp location for tests that modify source files (hot-patch tests).
// Done in JS so the webServer command is a simple `dx serve` with a `cwd`, which keeps
// stdout/stderr piping clean on both Unix and Windows cmd.exe.
function copyToTemp(src, dest) {
const absSrc = path.resolve(__dirname, src);
const absDest = path.resolve(__dirname, dest);
fs.rmSync(absDest, { recursive: true, force: true });
fs.cpSync(absSrc, absDest, { recursive: true });
}
let webServer = [];
let grep = undefined;
let grepInvert = undefined;
const repoRoot = path.resolve(__dirname, "..", "..");
const dx = path.join(repoRoot, "target", "release", process.platform === "win32" ? "dx.exe" : "dx");
const ALL_SERVERS = [
{
specs: ["liveview.spec.js"], port: 3030,
command: "cargo run --package dioxus-playwright-liveview-test --bin dioxus-playwright-liveview-test",
env: { CARGO_TERM_PROGRESS_WHEN: "never" }
},
{ specs: ["web.spec.js"], port: 9990, cwd: "web", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 9990` },
{ specs: ["web-routing.spec.js"], port: 2020, cwd: "web-routing", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 2020` },
{ specs: ["web-hash-routing.spec.js"], port: 2021, cwd: "web-hash-routing", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 2021` },
{ specs: ["fullstack.spec.js"], port: 3333, cwd: "fullstack", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 3333 --release` },
{ specs: ["fullstack-errors.spec.js"], port: 3232, cwd: "fullstack-errors", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 3232` },
{ specs: ["fullstack-mounted.spec.js"], port: 7777, cwd: "fullstack-mounted", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 7777` },
{ specs: ["fullstack-routing.spec.js"], port: 8888, cwd: "fullstack-routing", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 8888` },
{ specs: ["fullstack-spread.spec.js"], port: 7980, cwd: "fullstack-spread", command: `${dx} run --verbose --force-sequential --web --addr 127.0.0.1 --port 7980` },
{ specs: ["fullstack-hydration-order.spec.js"], port: 7979, cwd: "fullstack-hydration-order", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 7979` },
{ specs: ["fullstack-error-codes.spec.js"], port: 8124, cwd: "fullstack-error-codes", command: `${dx} run --force-sequential --addr 127.0.0.1 --port 8124` },
{ specs: ["nested-suspense.spec.js", "nested-suspense-no-js.spec.js"], port: 5050, cwd: "nested-suspense", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 5050` },
{ specs: ["nested-suspense-ssg.spec.js"], port: 6060, cwd: "nested-suspense", command: `${dx} run --bin nested-suspense-ssg --force-sequential --web --ssg --addr 127.0.0.1 --port 6060` },
{ specs: ["suspense-carousel.spec.js"], port: 4040, cwd: "suspense-carousel", command: `${dx} run --force-sequential --web --addr 127.0.0.1 --port 4040` },
{ specs: ["cli-optimization.spec.js"], port: 8989, cwd: "cli-optimization", command: `${dx} run --addr 127.0.0.1 --port 8989` },
{ specs: ["wasm-split.spec.js"], port: 8001, cwd: "wasm-split-harness", command: `${dx} run --bin wasm-split-harness --web --addr 127.0.0.1 --port 8001 --wasm-split --profile wasm-split-release` },
{ specs: ["default-features-disabled.spec.js"], port: 8002, cwd: "default-features-disabled", command: `${dx} run --force-sequential --addr 127.0.0.1 --port 8002` },
{ specs: ["web-patch.spec.js"], port: 9980, cwd: "web-hot-patch-temp", setup: () => copyToTemp("web-hot-patch", "web-hot-patch-temp"), command: `${dx} serve --verbose --force-sequential --web --addr 127.0.0.1 --port 9980 --hot-patch --exit-on-error` },
{ specs: ["web-patch-fullstack.spec.js"], port: 9981, cwd: "web-hot-patch-fullstack-temp", setup: () => copyToTemp("web-hot-patch-fullstack", "web-hot-patch-fullstack-temp"), command: `${dx} serve --verbose --force-sequential --web --addr 127.0.0.1 --port 9981 --hot-patch --exit-on-error` },
];
if (process.platform === "win32") {
webServer = [
{
cwd: path.join(process.cwd(), "windows-headless"),
command:
"cargo run --package dioxus-cli --release -- run --force-sequential",
port: 8787,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
];
grep = /windows/;
} else {
webServer = [
{
command:
"cargo run --package dioxus-playwright-liveview-test --bin dioxus-playwright-liveview-test",
port: 3030,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "web"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 9990',
port: 9990,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "web-routing"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 2020',
port: 2020,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "web-hash-routing"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 2021',
port: 2021,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 3333 --release',
port: 3333,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-errors"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 3232',
port: 3232,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-mounted"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 7777',
port: 7777,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-spread"),
command:
'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --web --addr "127.0.0.1" --port 7980',
port: 7980,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-routing"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 8888',
port: 8888,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "suspense-carousel"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 4040',
port: 4040,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "nested-suspense"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 5050',
port: 5050,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "nested-suspense"),
command:
'cargo run --package dioxus-cli --release -- run --bin nested-suspense-ssg --force-sequential --web --ssg --addr "127.0.0.1" --port 6060',
port: 6060,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-hydration-order"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --web --addr "127.0.0.1" --port 7979',
port: 7979,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "cli-optimization"),
command:
'cargo run --package dioxus-cli --release -- run --addr "127.0.0.1" --port 8989',
port: 8989,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "wasm-split-harness"),
command:
'cargo run --package dioxus-cli --release -- run --bin wasm-split-harness --web --addr "127.0.0.1" --port 8001 --wasm-split --profile wasm-split-release',
port: 8001,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "default-features-disabled"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --addr "127.0.0.1" --port 8002',
port: 8002,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "barebones-template"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --addr "127.0.0.1" --port 8123',
port: 8123,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
command:
'rm -rf ./web-hot-patch-temp && cp -r ./web-hot-patch ./web-hot-patch-temp && cd web-hot-patch-temp && cargo run --manifest-path ../../cli/Cargo.toml --release -- serve --verbose --force-sequential --web --addr "127.0.0.1" --port 9980 --hot-patch --exit-on-error',
port: 9980,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
command:
'rm -rf ./web-hot-patch-fullstack-temp && cp -r ./web-hot-patch-fullstack ./web-hot-patch-fullstack-temp && cd web-hot-patch-fullstack-temp && cargo run --manifest-path ../../cli/Cargo.toml --release -- serve --verbose --force-sequential --web --addr "127.0.0.1" --port 9981 --hot-patch --exit-on-error',
port: 9981,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
{
cwd: path.join(process.cwd(), "fullstack-error-codes"),
command:
'cargo run --package dioxus-cli --release -- run --force-sequential --addr "127.0.0.1" --port 8124',
port: 8124,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
},
];
ALL_SERVERS.push({ specs: ["windows.spec.js"], port: 8787, cwd: "windows-headless", command: `${dx} run --force-sequential` });
ALL_SERVERS.push({ specs: ["windows-hotpatch-fullstack.spec.js"], port: 8788, cwd: "windows-hotpatch-fullstack-temp", setup: () => copyToTemp("windows-hotpatch-fullstack", "windows-hotpatch-fullstack-temp"), command: `${dx} serve --verbose --force-sequential --hot-patch --exit-on-error` });
}
// Determine which servers to start based on spec files in argv and platform.
// On Windows only windows.spec.js runs (grep filter below), so don't bother
// starting servers for tests that will never execute — they just crash and
// pollute the logs.
const specArgs = process.argv.filter((a) => a.endsWith(".spec.js")).map((a) => path.basename(a));
const isWindows = process.platform === "win32";
const activeServers = specArgs.length > 0
? ALL_SERVERS.filter((s) => s.specs.some((spec) => specArgs.includes(spec)))
: isWindows
? ALL_SERVERS.filter((s) => s.specs.some((spec) => spec.includes("windows")))
: ALL_SERVERS.filter((s) => !s.specs.some((spec) => spec.includes("windows")));
// Run any setup functions (e.g. copying source to temp dirs for hot-patch tests)
// Only happens on initialize
//
// Build dx once: main process builds and sets env var; workers inherit it and skip.
// todo: implement proper fixtures https://www.youtube.com/watch?v=3i6cJUFO_m4
if (!process.env._DX_BUILT) {
for (const s of activeServers) {
if (s.setup) s.setup();
}
execSync("cargo build --package dioxus-cli --release", {
cwd: repoRoot,
env: { ...process.env, CARGO_TERM_PROGRESS_WHEN: "never" },
stdio: "inherit",
});
grepInvert = /windows/;
process.env._DX_BUILT = "1";
}
/**
* @see https://playwright.dev/docs/test-configuration
*/
module.exports = defineConfig({
testDir: ".",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "retain-on-failure",
// Increase the timeout for navigations to give dx time to build the project
navigationTimeout: 50 * 60 * 1000,
},
timeout: 50 * 60 * 1000,
/* Configure projects for major browsers */
webServer: activeServers.map((s) => ({
command: s.command,
port: s.port,
cwd: s.cwd ? path.join(__dirname, s.cwd) : __dirname,
timeout: 50 * 60 * 1000,
reuseExistingServer: !process.env.CI,
stdout: "pipe",
stderr: "pipe",
env: s.env,
})),
projects: [
{
name: "chromium",
grep,
grepInvert,
grep: process.platform === "win32" ? /windows/ : undefined,
grepInvert: process.platform !== "win32" ? /windows/ : undefined,
use: { ...devices["Desktop Chrome"] },
},
],
/* Run your local dev server before starting the tests */
webServer,
});
@@ -8,7 +8,7 @@ publish = false
[dependencies]
dioxus = { path = "../../dioxus", features = ["web"] }
wasm-bindgen = { version = "0.2.100" }
wasm-bindgen = { version = "0.2.114" }
web-sys = { version = "*", features = ["MouseEvent"] }
[workspace]
@@ -0,0 +1,78 @@
// @ts-check
const { test: base, expect } = require("@playwright/test");
const fs = require("fs");
const test = base.extend({
browser: async ({ playwright }, use) => {
const browser = await playwright.chromium.connectOverCDP("http://127.0.0.1:8788");
await use(browser);
await browser.close();
},
context: async ({ browser }, use) => {
const context = browser.contexts()[0];
await use(context);
},
page: async ({ context }, use) => {
const page = context.pages()[0];
await use(page);
},
});
const hotPatchTimeout = { timeout: 1000 * 60 * 2 };
test("windows fullstack hotpatch", async ({ page }) => {
const mainPath = "windows-hotpatch-fullstack-temp/src/main.rs";
const stylePath = "windows-hotpatch-fullstack-temp/assets/style.css";
let mainContent = fs.readFileSync(mainPath, "utf8");
let styleContent = fs.readFileSync(stylePath, "utf8");
// Reset any changes from prior runs.
mainContent = mainContent.replace(/Ok\(\s*2\s*\)/g, "Ok(1)");
mainContent = mainContent.replace("Click button! Count:", "Click me! Count:");
fs.writeFileSync(mainPath, mainContent);
styleContent = styleContent.replace("background-color: blue;", "background-color: red;");
fs.writeFileSync(stylePath, styleContent);
// ** Verify the initial fat build is working **
const main = page.locator("#main");
await expect(main).toContainText("Click me! Count: 0");
// Click and verify the server function works.
const button = page.locator("button#increment-button");
await button.click();
await page.waitForTimeout(1000);
await expect(main).toContainText("Click me! Count: 1");
// Verify initial CSS is applied.
await expect(main).toHaveCSS("background-color", "rgb(255, 0, 0)");
// ** Hot patch: change server fn return value and button text **
const updatedContent = mainContent
.replace(/Ok\(\s*1\s*\)/g, "Ok(2)")
.replace("Click me! Count:", "Click button! Count:");
fs.writeFileSync(mainPath, updatedContent);
// Wait for the hot patch to apply (text should update).
await expect(main).toContainText("Click button! Count: 1", hotPatchTimeout);
// Click and verify the new increment amount from the patched server fn.
await button.click();
await page.waitForTimeout(5000);
await expect(main).toContainText("Click button! Count: 3");
// ** Hot patch CSS **
const updatedStyle = styleContent.replace(
"background-color: red;",
"background-color: blue;"
);
fs.writeFileSync(stylePath, updatedStyle);
await page.waitForTimeout(1000);
// Wait for the CSS hot patch to apply.
await expect(main).toHaveCSS(
"background-color",
"rgb(0, 0, 255)",
hotPatchTimeout
);
});
@@ -0,0 +1,14 @@
[package]
name = "windows-hotpatch-fullstack"
edition = "2021"
version = "0.0.1"
publish = false
[dependencies]
dioxus = { path = "../../dioxus", features = ["fullstack"] }
[features]
desktop = ["dioxus/desktop"]
server = ["dioxus/server"]
[workspace]
@@ -0,0 +1,3 @@
#main {
background-color: red;
}
@@ -0,0 +1,38 @@
use dioxus::prelude::*;
const CSS: Asset = asset!("/assets/style.css");
fn app() -> Element {
let mut num = use_signal(|| 0);
rsx! {
document::Link {
href: CSS,
rel: "stylesheet",
}
button {
id: "increment-button",
onclick: move |_| async move {
let increment_amount = get_count().await.unwrap();
*num.write() += increment_amount;
},
"Click me! Count: {num}"
}
}
}
#[post("/api/get_count")]
async fn get_count() -> Result<i32> {
Ok(1)
}
fn main() {
let builder = dioxus::LaunchBuilder::new();
#[cfg(feature = "desktop")]
let builder = builder.with_cfg(
dioxus::desktop::Config::new().with_windows_browser_args("--remote-debugging-port=8788"),
);
builder.launch(app);
}