API hooks during restart for deno run --watch

Hello! I thought it would be super fun to further minimize repetitive tasks while manually testing a work-in-progress app during early and active development. So far, I love that the deno watcher can react to source file changes! One of my goals would be to automate mundane tasks in order to observe feedback faster as I: learn deno, prototype ideas, experiment with browser APIs / paradigms (e.g. saving state on document hide via session storage), etc. Specifically, I would love the ability to programmatically reload a specific Chrome tab (e.g. via puppeteer), anytime that I save code changes. So far (after about a couple days of wrestling with Bash scripting), I've got a crude working prototype for this use case. Yet, I can't help but wonder if there was a simpler way all along that I haven't discovered yet in my research attempts. I would absolutely love an idea like deno run -A --watch --watcher-debugging-port=<port> --watch-autostart=<true|false> app.ts that could maybe expose a WebSocket server on the debugging port for clients to listen to watcher events, perhaps including but not limited to: * process initial start * process initial fail * process about to restart * process successfully restarted * process failed to restart * end of watching (e.g. upon a kill -TERM) I imagine such an idea (or something similarly functional) would be simpler to understand, less brittle to maintain, and more functionally capable than a Bash 3.2 script that extracts a ws://<...> URL and coordinates between background subprocesses for <...>/MacOS/Google\ Chrome and deno run --watch <script-to-connect-puppeteer-and-serve-app-and-reload-page.ts>. For those curious enough, here is what my current Bash script does: * Makes an auxiliary fifo pipe * Spawns a new Chrome instance * as a background child process * using a hard-coded executable path (already installed on my computer) * with a --remote-debugging-port=0 and fixed value for --user-data-dir * redirecting std{out,err} into the fifo pipe * Awaits for Chrome's debug URL to appear * via blocking reads on the the fifo pipe * by pattern matching for a line that starts with DevTools listening on * and additionally extracting the websocket URL's hostport * Spawns my custom puppeteer script with Chrome's debug URL as an argument * as a background process * via a deno run --watch with very granular permissions like * --allow-env=PUPPETEER_PRODUCT * --allow-net=:8000,"${ws_hostport?}" * that roughly does Deno.serve({ onListen(...) { ... puppeteer.connect({ browserWSEndpoint, ... }) ... /* find or create browser page; goto App URL */ } }) * Sends a kill -TERM to the puppeteer script if Chrome process finishes earlier than usual (e.g. if I manually quit Chrome)
DAHDeno AI Helper9/13/2023
Based on the documentation, there isn't a built-in way to achieve exactly what you're looking for. The deno run --watch command does watch for file changes and restarts the process, but it doesn't provide hooks or events that you can listen to during the restart process. The documentation does mention that the file watcher automatically discovers files to watch based on the files contained in the module graph for the deno run subcommand. It also mentions that the --watch flag for deno run accepts an optional list of external files that should also be watched for changes. However, it doesn't provide a way to hook into the restart process or listen for events. As for the idea of exposing a WebSocket server on a debugging port for clients to listen to watcher events, this is not mentioned in the documentation. The documentation does mention that Deno supports the V8 Inspector Protocol used by Chrome, Edge, and Node.js, which allows you to debug Deno programs using Chrome DevTools or other clients that support the protocol. However, this is more about debugging your code and doesn't provide a way to listen for watcher events. In conclusion, while Deno provides some powerful features for watching files and debugging your code, it doesn't currently provide a built-in way to achieve exactly what you're looking for based on the documentation. Your current approach of using a Bash script might be the best solution for now. However, Deno is a rapidly evolving platform, so it's possible that more advanced features for interacting with the file watcher could be added in the future. 🦕
ABAltair 680b9/13/2023
I have an injectable Hot-Refresh that uses SSE rather than WS. https://gist.github.com/nhrones/85080a9cc993bf3629ceaf5bb8426a30
Hot Browser Refresh
Hot Browser Refresh. GitHub Gist: instantly share code, notes, and snippets.
Wow, this is a totally different approach and neat approach! If I understand it well enough, the major advantage over puppeteer (for a use case as simple as programmatically reloading-on-demand) is that it is more inherently supported across more browsers. Additionally, it appears less reliant on external libraries (namely: avoiding a dependency on puppeteer inside an instrumented helper script). (Though, I imagine this is not considered a dealbreaker for scenarios like manual testing.) I imagine the optimization to avoid reloads on pure CSS can be instrumented with puppeteer with similar complexity. I don’t know enough about SSE, so I don’t know how robust it will be when I allow the server app process to restart after saving server source code changes. I have not tested it out myself, so I can only speculate behavior in the worst case (upon glancing at the EventSource spec). The only situation I speculate being weary about is when I might accidentally save server code that compiles but fails to reach a healthy server, in which case I imagine that the browser would retry the connection for a couple times before deeming the server as unhealthy and closing the EventSource until the developer manually refreshes the browser.
ABAltair 680b9/14/2023
This deals only with client code! We watch for change to files in /src/. These are client code only. All code in /src is bundled to a bundle.js file that. The change (bundle.js) will stream a message to the script in the browser that forces the refresh. Changes to the server/service is not watched.
Gotcha. Thanks for sharing this paradigm! I’ll keep an open mind about this idea for when my server development code no longer changes heavily and whenever my focus transitions primarily to cross-browser client code
After a week of learning more things, I've learned that development mode for Deno fresh does auto-refresh the web page ([1]). I've observed that it does so via SSE and esbuild as well. It also takes advantage of things like ETags (and If-None-Match header) for static resources. Neat! I also noticed that whenever the local development server becomes unhealthy (e.g. upon quitting the deno task start process, or upon saving during incomplete / typoed / buggy code), the EventSource within Chrome seems to indefinitely retry the connection every 100ms or so. That goes against what I initially (and likely mistakenly) understood from the processing model of SSE ([2]). Not a big deal for local development, and perhaps something I'll depend on for now! [1] https://fresh.deno.dev/docs/getting-started/running-locally#:~:text=updates%20automatically [2] https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model
Running locally | Fresh docs
To start a Fresh project, just run deno task start. This will start the project with default permission flags, in watch mode.
ABAltair 680b9/20/2023
Chrome seems to indefinitely retry the connection every 100ms or so.
Chrome seems to indefinitely retry the connection every 100ms or so.
I think you'll find that in a spec somewhere. EventSource, unlike WS, is self-healing. The browser will continually try to reconnect.

Looking for more? Join the community!

Recommended Posts
deno compile -A npm:cowsay not workingHello, I am trying `deno compile -A npm:cowsay` and then following that with `./cowsay Hello World!`compiling issue with import { WebSocketServer } from "npm:ws@^8.14.1"Using this impot in a "deno run --unstable [etc...]" env works flawless / as intended but trying to Is there any way to get Deno to not statically analyze import()?I understand that statically analyzing and fetching dynamic import() calls is a good thing for perfoUsing Deno in Frontend.Hey, I was wandering if it is possible to use Deno for Vanilla Frontend development. I dont want to Excluding certain directories when using "walk"Hello, I'm writing a script that should crawl through a directory and search for a given text insideSyntax Error: Unexpected token 'export'Hello, We are using Supabase Deno Edge Functions and are getting this error while trying to import aDeno Deploy QuestionsHey there. We are using Supabase to run edge functions, which in turn built their feature on top of Bunle OAK static assets to the compiled binaryHi, I am currently switching from NodeJS to Deno, and so far so good! One of the reasons for this sThe requested module does not provide an export named 'default'I'm trying to export the following interface: ```import User from '../models/User.ts'; export defaI want to contribute to deno without disturbing my libs in linux . Is there a way?**Noob alert** I have been trying to contribute to deno . So i followed these instructions https://dTimezones in Dates?Hi everyone, what's the right way to create a `Date` with a specific timezone?Resolving Class constructor errorHello, I am currently trying to port a small test api from NodeJS to Deno. This code uses only NPM pKV list is returning an empty iterator, but data is there and gettable via getHello. To simplify things, I am setting a key of `["accounts", account.name]` but when I try to get Read permission & NPM importsHello, I'm using `--allow-read=.` to allow a script to read files in the current directory. The scriWebSocket connections killing setInterval()Hey Deno friends, it appears that websocket connections are somehow stopping the execution of setIntjsx in jsAll of my files containing JSX are in `.js` files. Is there an easy fix for this when running?