Skip to content

Commit

Permalink
No 馃憦 more 馃憦 server 馃憦 restarts 馃憦 on 馃憦 config 馃憦 changes (#4578)
Browse files Browse the repository at this point in the history
* feat: restart config on add, remove, update

* fix: reload for root project configs only

* fix: throw when userConfigPath can't resolve

* chore: changeset

* wip: remove normalizePath before writeFile

* refactor: invalidateWithCache -> isConfigReload

* wip: mustExist?

* debug: config loaded successfully

* debug: more logs

* debug: MORE logging

* fix: normalize resolved config path

* debug: yet MORE logging

* chore: bump proload

* fix: use file path, not URL.pathname

* Revert "wip: mustExist?"

This reverts commit 8ca8662.

* chore: remove console log

* feat: cleanup restart message, better invalid config handling

* chore: update lockfile

* chore: fix types

* fix: throw helpful error when config does not exist

* docs: remove "restart dev server" from integrations

* docs: make sure to restart -> try restarting

Co-authored-by: Nate Moore <[email protected]>
  • Loading branch information
bholmesdev and natemoo-re committed Sep 9, 2022
1 parent b6dd8b5 commit c706d84
Show file tree
Hide file tree
Showing 23 changed files with 155 additions and 124 deletions.
5 changes: 5 additions & 0 deletions .changeset/tricky-cows-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': minor
---

Restart dev server when config file is added, updated, or removed
2 changes: 1 addition & 1 deletion packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"@babel/plugin-transform-react-jsx": "^7.17.12",
"@babel/traverse": "^7.18.2",
"@babel/types": "^7.18.4",
"@proload/core": "^0.3.2",
"@proload/core": "^0.3.3",
"@proload/plugin-tsm": "^0.2.1",
"@types/babel__core": "^7.1.19",
"@types/html-escaper": "^3.0.0",
Expand Down
108 changes: 74 additions & 34 deletions packages/astro/src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/* eslint-disable no-console */

import type { Arguments as Flags } from 'yargs-parser'
import * as colors from 'kleur/colors';
import yargs from 'yargs-parser';
import { z } from 'zod';
import { normalizePath } from 'vite';
import add from '../core/add/index.js';
import build from '../core/build/index.js';
import { openConfig } from '../core/config.js';
import { openConfig, resolveConfigPath, resolveFlags, resolveRoot } from '../core/config.js';
import devServer from '../core/dev/index.js';
import { collectErrorMetadata } from '../core/errors.js';
import { debug, info, LogOptions, warn } from '../core/logger/core.js';
import { debug, error, info, LogOptions, warn } from '../core/logger/core.js';
import { enableVerboseLogging, nodeLogDestination } from '../core/logger/node.js';
import { formatConfigErrorMessage, formatErrorMessage, printHelp } from '../core/messages.js';
import preview from '../core/preview/index.js';
Expand All @@ -18,6 +19,8 @@ import { eventConfigError, eventError, telemetry } from '../events/index.js';
import { check } from './check/index.js';
import { openInBrowser } from './open.js';
import * as telemetryHandler from './telemetry.js';
import { appendForwardSlash } from '../core/path.js';
import { pathToFileURL } from 'url'

type Arguments = yargs.Arguments;
type CLICommand =
Expand Down Expand Up @@ -81,6 +84,16 @@ function resolveCommand(flags: Arguments): CLICommand {
return 'help';
}

async function handleConfigError(e: any, { cwd, flags, logging }: { cwd?: string; flags?: Flags, logging: LogOptions }) {
const path = await resolveConfigPath({ cwd, flags });
if (e instanceof Error) {
if (path) {
error(logging, 'astro', `Unable to load ${colors.bold(path)}\n`);
}
console.error(formatErrorMessage(collectErrorMetadata(e, path ? pathToFileURL(path) : undefined)) + '\n')
}
}

/**
* Run the given command with the given flags.
* NOTE: This function provides no error handling, so be sure
Expand Down Expand Up @@ -132,46 +145,73 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
}
}

let { astroConfig, userConfig, userConfigPath } = await openConfig({
cwd: root,
flags,
cmd,
logging,
});
let { astroConfig, userConfig } = await openConfig({
cwd: root,
flags,
cmd,
logging,
}).catch(async (e) => {
await handleConfigError(e, { cwd: root, flags, logging })
return {} as any;
});
if (!astroConfig) return;
telemetry.record(event.eventCliSession(cmd, userConfig, flags));

// Common CLI Commands:
// These commands run normally. All commands are assumed to have been handled
// by the end of this switch statement.
switch (cmd) {
case 'dev': {
async function startDevServer() {
const { watcher, stop } = await devServer(astroConfig, { logging, telemetry });

watcher.on('change', logRestartServerOnConfigChange);
watcher.on('unlink', logRestartServerOnConfigChange);
function logRestartServerOnConfigChange(changedFile: string) {
if (userConfigPath === changedFile) {
warn(logging, 'astro', 'Astro config updated. Restart server to see changes!');
}
}

watcher.on('add', async function restartServerOnNewConfigFile(addedFile: string) {
// if there was not a config before, attempt to resolve
if (!userConfigPath && addedFile.includes('astro.config')) {
const addedConfig = await openConfig({ cwd: root, flags, cmd, logging });
if (addedConfig.userConfigPath) {
info(logging, 'astro', 'Astro config detected. Restarting server...');
astroConfig = addedConfig.astroConfig;
userConfig = addedConfig.userConfig;
userConfigPath = addedConfig.userConfigPath;
await stop();
await startDevServer();
async function startDevServer({ isRestart = false }: { isRestart?: boolean } = {}) {
const { watcher, stop } = await devServer(astroConfig, { logging, telemetry, isRestart });
let restartInFlight = false;
const configFlag = resolveFlags(flags).config;
const configFlagPath = configFlag
? await resolveConfigPath({ cwd: root, flags })
: undefined;
const resolvedRoot = appendForwardSlash(resolveRoot(root));

const handleServerRestart = (logMsg: string) =>
async function (changedFile: string) {
if (
!restartInFlight &&
(configFlag
? // If --config is specified, only watch changes for this file
configFlagPath && normalizePath(configFlagPath) === normalizePath(changedFile)
: // Otherwise, watch for any astro.config.* file changes in project root
new RegExp(
`${normalizePath(resolvedRoot)}.*astro\.config\.((mjs)|(cjs)|(js)|(ts))$`
).test(normalizePath(changedFile)))
) {
restartInFlight = true;
console.clear()
try {
const newConfig = await openConfig({
cwd: root,
flags,
cmd,
logging,
isConfigReload: true,
});
info(logging, 'astro', logMsg + '\n');
astroConfig = newConfig.astroConfig;
await stop();
await startDevServer({ isRestart: true });
} catch (e) {
await handleConfigError(e, { cwd: root, flags, logging })
await stop();
info(logging, 'astro', 'Continuing with previous valid configuration\n');
await startDevServer({ isRestart: true });

}
}
}
});
};

watcher.on('change', handleServerRestart('Configuration updated. Restarting...'));
watcher.on('unlink', handleServerRestart('Configuration removed. Restarting...'));
watcher.on('add', handleServerRestart('Configuration added. Restarting...'));
}
await startDevServer();
await startDevServer({ isRestart: false });
return await new Promise(() => {}); // lives forever
}

Expand Down
5 changes: 3 additions & 2 deletions packages/astro/src/core/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import { fileURLToPath, pathToFileURL } from 'url';
import type yargs from 'yargs-parser';
import { resolveConfigURL } from '../config.js';
import { resolveConfigPath } from '../config.js';
import { debug, info, LogOptions } from '../logger/core.js';
import * as msg from '../messages.js';
import { printHelp } from '../messages.js';
Expand Down Expand Up @@ -97,7 +97,8 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
}
let configURL: URL | undefined;
const root = pathToFileURL(cwd ? path.resolve(cwd) : process.cwd());
configURL = await resolveConfigURL({ cwd, flags });
const rawConfigPath = await resolveConfigPath({ cwd, flags });
configURL = rawConfigPath ? pathToFileURL(rawConfigPath) : undefined;
applyPolyfill();

if (configURL) {
Expand Down
Loading

0 comments on commit c706d84

Please sign in to comment.