Sandpack/nodebox-runtime

Getting started

robtweed opened this issue · 12 comments

It's not clear from the documentation what's needed to bootstrap the nodebox environment in the browser. eg is nodebox dependent on first loading sandpack into the browser?

I think your worked "getting started" example needs to start from the absolute ground up - ie several basic steps earlier than you do - for very interested dimwits like me to get it and actually get something working :-)

+1 to this. There's definitely some intermediary step that I'm missing. It looks like the code is being executed in the browser as the getting started code is referencing the document object, yet the import URL starts with an @ which throws an error as the browser is expecting relative URLs to start with "/", "./", or "../".

Hey, thanks for the feedback. I'm more than happy to make the documentation more clear. But first, I'd like to understand how and what made you to come up with these misunderstandings.

  1. What did make you think Nodebox depends on Sandpack? I guess we don't mention Sandpack on Getting Started, so I'm curious to understand where we're miscomunicating it.
  2. Which "getting started example" are you referring to? I guess you're taking about Nodebox getting started and not Sandpack one. But if it's confusing, we can make it better.
  3. What do you think about this example here? Does it make clear how to use Nodebox? https://codesandbox.io/p/sandbox/priceless-bash-nlrrz4?file=%2Findex.js

Looking forward to solve it


@CamdynR, you mention an issue when trying to run an example, right? Could you please provide a sandbox about this issue or point to me which example you tried to run?

Hi - thanks for the response.

I think the problem is that I believe I'm missing something fundamental about how to get started with Nodebox - in essence what the starting environment/setup is.

Let me explain where I'm coming from: on reading about Nodebox it's selling me the intriguing idea of being able to run Node.js in a browser, which I'd love to be able to do: I can see all the advantages and benefits.

So I understand how to use and run Node.js on a server. And I understand how to fire up stuff such as Service Workers in browsers. Clearly to be able to run Node.js in a browser there's going to have to be a sequence of initial "bootstrapping" steps in which the browser loads the code necessary to run Node.js.

So when I read the Nodebox "Getting Started" steps I'm first told to npm install @codesandbox/nodebox OK, so I'd assume (perhaps naively) that this is on a server on which I've installed Node.js and from which I'm going to fetch the bootstrapping logic into my browser.

Next in "Configure and Connect" there's some lines of code to import Nodebox and instantiate the Nodebox emulator. But I'm not told where to enter these lines of code - into a file somewhere perhaps? A file on my server? A file that is fetched somehow into my browser?

On the other hand, perhaps I'm supposed to have already loaded and started your browser-based IDE and be entering this stuff into that in the browser. That's fine if that's the case but, as a standalone "Getting Started" document, you've not made that clear. And also if that's the case, it perhaps means that Nodebox has a pre-requisite IDE environment that is beyond what I'd expected and/or was hoping for.

As I say, I am sure the misunderstanding is on my side, but I'd suggest that there are likely others who will come to your repository's documentation with a similarly naive starting point.

The solution, I'd suggest, is to make completely clear what the starting environment is at the beginning of your "Getting Started" (and how to get that starting environment up and running) - and where/how I'm supposed to be entering the commands and code you go on to describe, such that I end up with a Node.js environment in my browser that I can then start playing with. Don't assume the reader knows much about anything.

Hey, @robtweed. Those are valid points, allow me to elaborate below.

So when I read the Nodebox "Getting Started" steps I'm first told to npm install @codesandbox/nodebox OK, so I'd assume (perhaps naively) that this is on a server on which I've installed Node.js and from which I'm going to fetch the bootstrapping logic into my browser.

This isn't correct. You install @codesandbox/nodebox in the client application where you wish to run Node.js. For example, imagine you're developing a UI library for Next.js and you want to run the actual Next.js project in your documentation to showcase your components. You install Nodebox in your documentation's app to achieve that. There are no servers involved whatsoever.

Next in "Configure and Connect" there's some lines of code to import Nodebox and instantiate the Nodebox emulator. But I'm not told where to enter these lines of code - into a file somewhere perhaps? A file on my server? A file that is fetched somehow into my browser?

A good one, I will clarify this in the documentation 👍

Basically, you need to instantiate and initialize Nodebox once in your application's context. Based on how you're building your application, you would have to set up Nodebox in a different place. This is your framework's contextual knowledge but I will try including a few examples so it's clear when this must happen.

And also if that's the case, it perhaps means that Nodebox has a pre-requisite IDE environment that is beyond what I'd expected and/or was hoping for.

No, you don't need our IDE to use Nodebox. Nodebox is a standalone library that you can plugin anywhere in your client project and gain the superpowers of executing Node code in the browser.

Thanks for the suggestions, I will use them to improve our current documentation and make the starting process explicitly clear.

So this is a lot clearer now but I think there's one additional assumption being made (though I may be wrong on this): are you assuming that the user will use WebPack or some other bundler to create the client JS file? If so, would there be a way to use vanilla JS instead (my preferred approach these days)?

So this is a lot clearer now but I think there's one additional assumption being made (though I may be wrong on this): are you assuming that the user will use WebPack or some other bundler to create the client JS file? If so, would there be a way to use vanilla JS instead (my preferred approach these days)?

Yes, you can import this file directly using a standars esmodule import https://unpkg.com/@codesandbox/nodebox@0.1.0/build/index.mjs

@robtweed, no, we don't assume that. The way you author your application, including the way you bundle it, is entirely up to you. Nodebox is not different in that regard from any other library you may use, like axios.

Nice! I have this now working cleanly - obviously not actually doing anything but this looks like enough to get properly started!! :-)

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Nodebox test</title>
  </head>
  <body>
    <script type="module" src="/js/nodebox.js"></script>
    <iframe id="preview"></iframe>
  </body>
</html>

/js/nodebox.js:

(async () => {
  const {Nodebox} = await import('https://unpkg.com/@codesandbox/nodebox@0.1.0/build/index.mjs');
  const emulator = new Nodebox({
    iframe: document.getElementById('preview'),
  });
  await emulator.connect();

  console.log(333333);
})();

I'm able to get the simple Node.js web server example running in my browser - in the iframe I see localhost:3000 as you'd expect

However I'm now struggling to understand how to use/access that web server on port 3000. In the browser's console I get a connection rejected error if I try:

let resp = await fetch('http://127.0.0.1:3000/')

or

let resp = await fetch('http://localhost:3000/')

I see in the documentation:

"it will be directly available at https://{projectId}-3000.nodebox-runtime.codesandbox.io"

but where do I get the value of {projectId}?

I assume this is a notional endpoint that is intercepted in the browser's Service Worker?

Thanks for helping me "get this"! It is looking impressively cool as I begin to understand its moving parts

A further observation - if I fire up my test and leave it for a while, I get a bunch of errors reported in the browser's developer tools console. Here's an example:

Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'MessagePort': A ReadableStream could not be cloned because it was not transferred.
at _0x218a24 (https://ao137bo-3000.nodebox.codesandbox.io/__csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105:17994)
_0x218a24 @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
await in _0x218a24 (async)
_0x4c8e7b @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
_0x267b9b @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
(anonymous) @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
The FetchEvent for "https://ao137bo-3000.nodebox.codesandbox.io/cdn-cgi/rum?" resulted in a network error response: the promise was rejected.
Promise.then (async)
(anonymous) @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
__csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105 Uncaught (in promise) Error: Failed to handle POST https://ao137bo-3000.nodebox.codesandbox.io/cdn-cgi/rum? request: no response received from the BroadcastChannel within timeout. There's likely an issue with the bridge/worker communication.
at __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105:19749
(anonymous) @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
setTimeout (async)
_0x4c8e7b @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
_0x267b9b @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
(anonymous) @ __csb_sw.hbay8izykji14sk39wip2vjr7ni1q45.js:105
vaafb692b2aea4879b33c060e79fe94621666317369993:1 POST https://ao137bo-3000.nodebox.codesandbox.io/cdn-cgi/rum? net::ERR_FAILED

From this I guess I can see that the projectId is ao137bo - but any attempt to use that URL fails too

Any ideas what's going on (this is running in Chrome on Mac btw)?

I still get that error, but opening a new tab in the latest version of Chrome and typing:

https://jp13752-3000.nodebox.codesandbox.io/

and I successfully got "Hello World" returned! :-)

Perhaps the problem I reported earlier was because I wasn't using the latest version of Chrome within one of my VMs

I got the jp13752 from looking in Developer Tools/Applications and it showing up in various places such as Local Storage. However I assume there's some API I can use to obtain it during initialisation? That projectId changes on every reload of course.

I still see that set of errors reported for the mysterious POST request to /cdn-cgi/rum but the Node.js web server seems to now be running and accessible via that codesandbox.io URL, so I'm not sure what that's all about

OK I think I actually figured out what I need to know, so I think this issue can be closed. Many thanks for your help, but hopefully this thread will help with documentation and perhaps others trying to wrap their heads around this awesome stuff.

The vital bit of code I needed to add to my script was:

const {id} = await shell.runCommand('node', ['index.js']);
const { url } = await emulator.preview.getByShellId(id);

and url is what I need to use to access the Node.js http server