Squigil’s House

Cross post: Squigil's House - The Gallery - Glitch Community Forum

Anyone find Fastly Compute to be missing a certain development speed? And a sort of “develop from any computer” element?

For a while I’ve been fiddling with a Compute app with their JS SDK that would do, in short, eval(kv_store_get(url)). Super fast iteration time. Update KV store entry, change deployed in milliseconds.

I now have a web-compatible Visual Studio Code extension for managing those KV store entries that’s shaping up:

squigil-edit

Gradual start

  1. Have a proper enough development computer, one with npm etc. for running the Fastly CLI. This is only for this setup, and you don’t need to be at this computer to develop stuff later. I am interested whether this is possible to do without a full development environment, but I have not looked into it.
  2. Get the source code GitHub - wh0/squigil.
  3. Go to https://squigil.edgecompute.app/admin-setup.html, click generate.
  4. Save the secret somewhere.
  5. Copy the '...': true, line, add it to init/admin/index.js squigil/init/admin/index.js at master · wh0/squigil · GitHub in the allowedSecretDigests dictionary.
  6. Run npm run deploy and follow interactive instructions. It’ll ask you about several files to use in the KV store, but they should already be set, so just press enter on those.
  7. When it’s deployed, it’ll be at a domain. If you didn’t set up a custom domain, it’ll be (something).edgecompute.app. Remember this or save it.
  8. Go to https://vscode.dev/ or get Visual Studio Code or a compatible editor.
  9. Install this extension Squigil's Home Phone - Visual Studio Marketplace.
  10. Press F1 or Ctrl+Shift+P or similar and use “Drop by Squigil’s House.”
  11. Select Allow. In the Installation Alias chooser, select “Other” and then enter your installation’s domain from the deployment earlier. In the Admin Secret input, enter your secret from the admin setup earlier.

If there’s any interest, I’ll see if I can write some more getting started guides.

4 Likes

@wh0 hey nice to see you around these parts :wink:

This is a super cool project, but Fastly Compute is a little different from Glitch’s experience in that it requires an explicit compiler build before pushing the code up to Fastly. Continuously changing the code on the platform this way will likely blow out trial resource allocations quickly.

If the goal is to have an in-browser editing experience, I’d recommend using GitHub Codespaces paired with a GitHub Action that can automate the build/deploy step every time your main branch changes. Codespaces isn’t a perfect Glitch editor replacement by any stretch, but it’s a supported path that won’t introduce any surprise bugs.

hi @aspires, thanks for taking a look at this project :folded_hands:

you’re referring to continuously rebuilding and deploying new versions of the Compute app, right? that indeed is costly.

avoiding that is sort of the charter of this project. so the editing workflow doesn’t change the “code” on the platform. it updates a KV entry. the “code” of the compute app serving this is an interpreter, which incidentally already existed, as the JS SDK supports eval.

updating KV entries isn’t free either, but I’m under the impression that updates produced by a solo dev typing occasionally is a modest level of use.

here’s my usage over the past ~month of myself building the included tooling (and precursors :laughing: ):

I don’t know how to look at KV usage, but each of these would have taken 1-2 reads and 0-1 writes.

this all is true, and something like this is probably how normal work will have to be done, when it involves using dependencies from npm, codebases that need a build tool, etc. I do appreciate Fastly’s tutorials on using Compute in this way.

1 Like

There’s still a big difference from the way that platforms like Glitch worked.

In Glitch, after you edit the code, a container is launched running a Node server which parses your JavaScript code and prepares to receive requests. When requests arrive, they are handled by the code already loaded into the interpreter.

In Fastly Compute, there are no long-lived instances; every request which lands on the Fastly edge network causes a new instance to be launched. In your case, that instance will then retrieve some JavaScript code from KV Store and run it through eval before executing it to handle the request. When the handling of that request is complete, all the parsing/evaluation results will be thrown away, to be recreated when the next request arrives.

that is consistent with my understanding of Fastly Compute.

this project isn’t meant to turn Fastly Compute into a Glitch-compatible Ubuntu server. when I build on this, I’m still writing Fastly Compute code that runs in a short-lived per-request-isolated environment.

I guess that’s worth clarifying for people coming to this thread.

if you don’t actually want to learn Fastly Compute or if you wanted to build something that doesn’t fit into Fastly Compute’s capabilities in the first place e.g. with long running requests, this project doesn’t help you get away from that.

and that all is fine, right? anyone who’s already made their way here is here because they believe in this architecture.

1 Like

Hey wh0, this is so so cool, thank you for sharing it with us and the rest of the community! It’s really inspiring to see that you thought outside the box to make it easier to develop on Compute. The Squigil character is very cute too.

It makes sense from a performance and cost management perspective that the normal Compute deployment flow has the build phase where we “warm up” the JavaScript engine so that it doesn’t have to happen on every request, but you raise a very good point that this is probably an unnecessary step for prototyping that only slows things down from the perspective of a developer.

I’m imagining an A+ development experience that uses the technique you’ve shared here, along with what I think is missing – a final “publish” step so that once you’re done fiddling with the code, it does go through that build stage which would keep things fast and costs low. You could of course continue hacking away in this prototyping environment after that and re-publish as many times as you like.

Perhaps this functionality would be a useful improvement to Fastly Fiddle?

Either way, I appreciate you sharing. I’ll have to test it out next week. I look forward to seeing what you can create with this :slight_smile:

2 Likes

“publish” step sounds good. I’m somewhat doing a publish step already, although only to publish reasonably stabilized scripts on github rather than to compile them into optimized wasm. what I’m reading above though is that there are CI setups that put the build+deploy automation within reach. I’ll probably look into that if I start hitting the 50 ms CPU limit with longer scripts/scripts that do more work.

not sure if this would be a net benefit for Fastly Fiddle. it’s specific to JavaScript and it’s really hacky, e.g. with imports not being supported.

2 Likes

When you get an opportunity, please also compare it our normal local development workflow, which uses fastly compute serve –watch to build and run the service in Viceroy, and automatically rebuilds/relaunches when the source code is changed. We’d be curious to see your thoughts on that workflow too!

I used viceroy a lot in getting the really early versions of this set up. Here’s that comparison:

quality CLI+Viceroy Squigil’s House
time overhead to run updated code a few seconds, I can handle it. the js sdk doesn’t do much compilation. there’s only wizer and whatever viceroy’s startup delay is feels like less than a second. note that I’ve only tried editing and viewing in the same region
where development happens on a certain computer. may be a remote computer that you connect to from multiple computers, possibly with a subscription fee any computer, in web browser. have to log in though
auto rebuild available with --watch. restarts when files referenced in [local_server] change too. ironically I didn’t know about this while bootstrapping this project. starter had non-watch “start” script provided, so I never looked at the manual :laughing: more or less equivalent to auto save in editor
state across rebuilds reinitialized to [local_server] spec. this behavior can be helpful in some use cases persists. this behavior can be helpful in other use cases
language support any sdk’s wasm output js only. theoretically possible to extend to other languages that have wasm interpreter
js feature support starlingmonkey/spider monkey, wintertc stuff same, but imports are broken. need app rebuild to export new modules in the future
dev env separation local server is intrinsically separate from production site :smiling_face_with_sunglasses:
backup+version control it’s just files, easy to use git or other tools dragging around folders to make copies lol
3 Likes

Thank you! That’s a very detailed response and far beyond what I was hoping for :slight_smile:

More getting started guides after all. These are for when you’ve set up the VS Code extension.

Making a web page

  1. Right-click the public directory.
  2. Click “New File…”
  3. Type in a filename and press enter.
  4. Literally type out HTML code.
    --- /dev/null
    +++ b/public/note.html
    +<!doctype html>
    +<meta name="viewport" content="width=device-width,initial-scale=1">
    +<p>
    +	ay
    +</p>
    
  5. Open that file on your site without the public/ part, e.g. at https://???.edgecompute.app/note.html.

Adding resources

  1. Create a new file similar to above, or right-click the public directory and click “Upload.”
    --- /dev/null
    +++ b/public/note.css
    +body {
    +	font-family: sans-serif;
    +}
    
  2. Open index.js and add logic to serve it with the right content type.
    --- a/index.js
    +++ b/index.js
     if (key.endsWith('.html')) {
     	contentType = 'text/html';
    +} else if (key.endsWith('.css')) {
    +	contentType = 'text/css';
     } else {
     	contentType = 'application/octet-stream';
     }
    
  3. Have the web page use it.
    --- a/public/note.html
    +++ b/public/note.html
     <meta name="viewport" content="width=device-width,initial-scale=1">
    +<link rel="stylesheet" href="note.css">
    
  4. Check the page, e.g. at https://???.edgecompute.app/note.html, and it should be using the external stylesheet.

Making a dynamic page

  1. Click the “New File…” button.
  2. Type a directory name followed by /index.js.
    I found out that VS Code makes the parent directories for you this way.
  3. Type // ~ // followed by code… see below.
    --- /dev/null
    +++ b/info/index.js
    +// ~ //
    +const info = {
    +	userAgent: fetchEvent.request.headers.get('User-Agent'),
    +	entranceKey,
    +	innerPath,
    +	pop: builtinModules.fastlyEnv.env('FASTLY_POP'),
    +};
    +return new Response(JSON.stringify(info), {headers: {'Content-Type': 'application/json'}});
    
    Basically the content of this file gets used as the body of an async function with some arguments given, and it should return a Response.
    Currently the arguments are:
    fetchEvent: FetchEvent
    entranceKey: string // e.g. `a/a/index.js` for request URL path `/a/a/~/b/b`
    innerPath: string // e.g. `/b/b` for request URL path `/a/a/~/b/b`
    builtinModules: {
    	// see docs https://js-compute-reference-docs.edgecompute.app/docs/
    	fastlyAcl: import('fastly:acl'),
    	...,
    }
    
    See the code squigil/src/index.js at 05e163985725701ab9a5a982adc390dbe4412d91 · wh0/squigil · GitHub in case this gets out of date.
  4. Now you should be able to go to e.g. https://???.edgecompute.app/info/~/ and see some JSON.

Running some code as the admin

  1. You make a POST request to /admin/~/eval like this:
    SQUIGIL_ADMIN_SECRET=your_admin_secret \
    curl \
    	--variable %SQUIGIL_ADMIN_SECRET \
    	--variable 'body=return new Response('"'"'hi\n'"'"');' \
    	-X POST \
    	--expand-header 'Authorization: Bearer {{SQUIGIL_ADMIN_SECRET}}' \
    	--expand-url 'https://???.edgecompute.app/admin/~/eval?body={{body:url}}'
    
    That, similar to the dynamic page, runs some code as the body of an async function with some arguments given, and it should return a Response.
    Currently the arguments are:
    fetchEvent: FetchEvent
    builtinModules: {
    	// see docs https://js-compute-reference-docs.edgecompute.app/docs/
    	fastlyAcl: import('fastly:acl'),
    	...,
    }
    searchParams: URLSearchParams
    
    See the code squigil/init/admin/index.js at 05e163985725701ab9a5a982adc390dbe4412d91 · wh0/squigil · GitHub in case this gets out of date.
  2. That should give the response constructed by the code, which is the message hi.
3 Likes