Skip to content

fix build --watch #1189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 8, 2025
Merged

fix build --watch #1189

merged 4 commits into from
Aug 8, 2025

Conversation

dominikg
Copy link
Member

@dominikg dominikg commented Aug 6, 2025

  • add test mode for build --watch
  • add test setup that works with page refresh after watch rebuild
  • fix issues uncovered

fixes #1186 and #1188

due to getModuleInfo in load hook not returning cached data for unchanged modules, compiled css was not loaded and instead vites own fallback load plugin returned the uncompiled file content.

To fix it, this PR caches the css output separately and returns it on rebuild.

"test:unit": "vitest run",
"test:serve": "vitest run -c vitest.config.e2e.ts",
"test:build": "cross-env TEST_BUILD=1 vitest run -c vitest.config.e2e.ts",
"test:build:watch": "cross-env TEST_BUILD_WATCH=1 vitest run -c vitest.config.e2e.ts",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build --watch was not tested at all before but 2 recent issues highlighted that we can't just depend on it being tested by vite itself

@@ -1,5 +1,15 @@
import path from 'node:path';
import fs from 'node:fs';
import MagicString from 'magic-string';

function replaceWithSourceMap(code, value, replacement) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the missing sourcemap lead to error logs, add them to allow easier debugging and assertions that no unexpected errors happened

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is basically a copy of the hmr test, with some changed asserts (state cannot be preserved, manual page reloads more often)

const startedPromise = new Promise((resolve, reject) => {
stdoutListener = (data) => {
const str = data.toString();
const match = str.match(/built in \d+ms\./);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initial build of build --watch logs "build in 123ms." at the end. wait for that to ensure we don't try to load the preview before that is done

console.error(`failed to treekill serverprocess ${serverProcess.pid}`, err);
}
resolve();
for (const p of [watchProcess, serverProcess]) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure build --watch is killed alongside preview

};
try {
await startedOnPort(serverProcess, port, 20000);
await startedOnPort(serverProcess, port, 10000);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must be shorter than vitests 20s timeout, otherwise failed start error can be swallowed

} catch (e) {
const maxTries = isCI && isWin ? 3 : 1;
let lastErr;
for (let i = 1; i <= maxTries; i++) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we need this, unlike hmr where edits can happen super fast there is a build step in between here so it should work the first time always

let completed = false;
while (timeleft > 0) {
await sleep(pollInterval);
if (logs.some((text, i) => i > startIdx && text.match(/\d+ modules transformed\./))) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build watch logs the number of transformed modules each time a watch change triggered it.

"build": "run-s build:client build:server",
"build:client": "vite build --ssrManifest .vite/ssr-manifest.json --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.js --outDir dist/server",
"build": "vite build --app",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for --watch to work swiched this over to environment api builder, the previous scripts would not work as they relied on being called in sequence.

@@ -71,7 +77,8 @@ const getUniqueTestPort = async (testRoot, testName, isBuild) => {
if (idx < 0) {
throw new Error(`failed to find ${testName} in ${testRoot}`);
}
return (isBuild ? 5500 : 3500) + idx;
const basePort = testMode === 'build:watch' ? 7500 : testMode === 'build' ? 5500 : 3500;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new portrange so parallel tests of build and build:watch never overlap in ports

@@ -21,6 +21,17 @@ const exclude = [
'**/cypress/**',
'**/.{idea,git,cache,output,temp}/**'
];
const include = ['./packages/e2e-tests/**/*.spec.[tj]s'];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure that the build-watch test is only run during test:build:watch to avoid extra work

@@ -37,6 +54,8 @@ export function loadCompiledCss(api) {
}
css.moduleType = 'css';
return css;
} else {
log.warn(`failed to load virtual css module ${id}`, undefined, 'load');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with this fix, this should not happen anymore, but we want to know if it does because that would be another issue.

@dominikg dominikg marked this pull request as ready for review August 7, 2025 13:19
@bluwy bluwy linked an issue Aug 8, 2025 that may be closed by this pull request
@dominikg dominikg merged commit 3a6976a into main Aug 8, 2025
8 checks passed
@dominikg dominikg deleted the fix/build-watch branch August 8, 2025 10:05
@github-actions github-actions bot mentioned this pull request Aug 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Watch mode generates corrupt CSS on second build Version 6 breaksbuild --watch throwing [commonjs] [postcss] Unknown word xxx
2 participants