|
1 | 1 | import { debounce } from 'perfect-debounce'; |
| 2 | +import chokidar from 'chokidar'; |
2 | 3 | import { |
3 | 4 | BuildStepOutput, |
4 | 5 | EntrypointGroup, |
@@ -28,6 +29,7 @@ import { |
28 | 29 | mapWxtOptionsToRegisteredContentScript, |
29 | 30 | } from './utils/content-scripts'; |
30 | 31 | import { createKeyboardShortcuts } from './keyboard-shortcuts'; |
| 32 | +import { isBabelSyntaxError, logBabelSyntaxError } from './utils/syntax-errors'; |
31 | 33 |
|
32 | 34 | /** |
33 | 35 | * Creates a dev server and pre-builds all the files that need to exist before loading the extension. |
@@ -156,8 +158,25 @@ async function createServerInternal(): Promise<WxtDevServer> { |
156 | 158 | const keyboardShortcuts = createKeyboardShortcuts(server); |
157 | 159 |
|
158 | 160 | const buildAndOpenBrowser = async () => { |
159 | | - // Build after starting the dev server so it can be used to transform HTML files |
160 | | - server.currentOutput = await internalBuild(); |
| 161 | + try { |
| 162 | + // Build after starting the dev server so it can be used to transform HTML files |
| 163 | + server.currentOutput = await internalBuild(); |
| 164 | + } catch (err) { |
| 165 | + if (!isBabelSyntaxError(err)) { |
| 166 | + throw err; |
| 167 | + } |
| 168 | + logBabelSyntaxError(err); |
| 169 | + wxt.logger.info('Waiting for syntax error to be fixed...'); |
| 170 | + await new Promise<void>((resolve) => { |
| 171 | + const watcher = chokidar.watch(err.id, { ignoreInitial: true }); |
| 172 | + watcher.on('all', () => { |
| 173 | + watcher.close(); |
| 174 | + wxt.logger.info('Syntax error resolved, rebuilding...'); |
| 175 | + resolve(); |
| 176 | + }); |
| 177 | + }); |
| 178 | + return buildAndOpenBrowser(); |
| 179 | + } |
161 | 180 |
|
162 | 181 | // Add file watchers for files not loaded by the dev server. See |
163 | 182 | // https://github.com/wxt-dev/wxt/issues/428#issuecomment-1944731870 |
@@ -187,7 +206,7 @@ function createFileReloader(server: WxtDevServer) { |
187 | 206 | const cb = async (event: string, path: string) => { |
188 | 207 | changeQueue.push([event, path]); |
189 | 208 |
|
190 | | - await fileChangedMutex.runExclusive(async () => { |
| 209 | + const reloading = fileChangedMutex.runExclusive(async () => { |
191 | 210 | if (server.currentOutput == null) return; |
192 | 211 |
|
193 | 212 | const fileChanges = changeQueue |
@@ -256,6 +275,14 @@ function createFileReloader(server: WxtDevServer) { |
256 | 275 | // Catch build errors instead of crashing. Don't log error either, builder should have already logged it |
257 | 276 | } |
258 | 277 | }); |
| 278 | + |
| 279 | + await reloading.catch((error) => { |
| 280 | + if (!isBabelSyntaxError(error)) { |
| 281 | + throw error; |
| 282 | + } |
| 283 | + // Log syntax errors without crashing the server. |
| 284 | + logBabelSyntaxError(error); |
| 285 | + }); |
259 | 286 | }; |
260 | 287 |
|
261 | 288 | return debounce(cb, wxt.config.dev.server!.watchDebounce, { |
|
0 commit comments