Handle server restart from Vite plugins (#5849)

This commit is contained in:
Bjorn Lu 2023-01-14 16:51:01 +08:00 committed by GitHub
parent e818cc0466
commit 8c100a6fe6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 28 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Handle server restart from Vite plugins

View file

@ -142,35 +142,39 @@ export async function createContainerWithAutomaticRestart({
}, },
}; };
function handleServerRestart(logMsg: string) { async function handleServerRestart(logMsg: string) {
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
const container = restart.container; const container = restart.container;
return async function (changedFile: string) { const { container: newContainer, error } = await restartContainer({
if (shouldRestartContainer(container, changedFile)) { beforeRestart,
const { container: newContainer, error } = await restartContainer({ container,
beforeRestart, flags,
container, logMsg,
flags, async handleConfigError(err) {
logMsg, // Send an error message to the client if one is connected.
async handleConfigError(err) { await handleConfigError(err);
// Send an error message to the client if one is connected. container.viteServer.ws.send({
await handleConfigError(err); type: 'error',
container.viteServer.ws.send({ err: {
type: 'error', message: err.message,
err: { stack: err.stack || '',
message: err.message,
stack: err.stack || '',
},
});
}, },
}); });
restart.container = newContainer; },
// Add new watches because this is a new container with a new Vite server });
addWatches(); restart.container = newContainer;
resolveRestart(error); // Add new watches because this is a new container with a new Vite server
restartComplete = new Promise<Error | null>((resolve) => { addWatches();
resolveRestart = resolve; resolveRestart(error);
}); restartComplete = new Promise<Error | null>((resolve) => {
resolveRestart = resolve;
});
}
function handleChangeRestart(logMsg: string) {
return async function (changedFile: string) {
if (shouldRestartContainer(restart.container, changedFile)) {
handleServerRestart(logMsg);
} }
}; };
} }
@ -178,9 +182,13 @@ export async function createContainerWithAutomaticRestart({
// Set up watches // Set up watches
function addWatches() { function addWatches() {
const watcher = restart.container.viteServer.watcher; const watcher = restart.container.viteServer.watcher;
watcher.on('change', handleServerRestart('Configuration updated. Restarting...')); watcher.on('change', handleChangeRestart('Configuration updated. Restarting...'));
watcher.on('unlink', handleServerRestart('Configuration removed. Restarting...')); watcher.on('unlink', handleChangeRestart('Configuration removed. Restarting...'));
watcher.on('add', handleServerRestart('Configuration added. Restarting...')); watcher.on('add', handleChangeRestart('Configuration added. Restarting...'));
// Restart the Astro dev server instead of Vite's when the API is called by plugins.
// Ignore the `forceOptimize` parameter for now.
restart.container.viteServer.restart = () => handleServerRestart('Restarting...');
} }
addWatches(); addWatches();
return restart; return restart;

View file

@ -180,4 +180,35 @@ describe('dev container restarts', () => {
await restart.container.close(); await restart.container.close();
} }
}); });
it('Is able to restart on viteServer.restart API call', async () => {
const fs = createFs(
{
'/src/pages/index.astro': ``,
},
root
);
const { astroConfig } = await openConfig({
cwd: root,
flags: {},
cmd: 'dev',
logging: defaultLogging,
});
const settings = createSettings(astroConfig, fileURLToPath(root));
let restart = await createContainerWithAutomaticRestart({
params: { fs, root, settings },
});
await startContainer(restart.container);
expect(isStarted(restart.container)).to.equal(true);
try {
let restartComplete = restart.restarted();
await restart.container.viteServer.restart();
await restartComplete;
} finally {
await restart.container.close();
}
});
}); });