This worked well, until someone went – hey, we should also use this cool language on the server side. So node.js was born, and it added extra APIs for stuff like filesystem access and web servers that the V8 sandbox didn't allow.
Then someone went – hey, wouldn't it be neat to run all this cool node.js code in the browser? So Nodebox and Webcontainers were born that wrote a compatibility layer and added pollyfills for all the node.js-specific APIs that were missing in V8, and so some of this code was able to run in the browser.
My question is – why couldn't all this code run directly on the browser in the first place without Node.js and Nodebox?
Modern computers and their software are all Rube Goldberg machines, and we're only adding new parts instead of finally having a critical look at the whole and rethink the monstrosity from the ground up (considering all we know by now, of course).
It is _technically_ cool but I feel like this existing is a definite step backwards with regards to Node.js' lack of modern web APIs.
Software like this relieves pressure in moving from Node.js specific APIs towards standardised web APIs and in addition to that itself boasts about portability by ignoring modern features too. From their WebContainer vs Nodebox FAQ:
Nodebox runs on any browser because it was built from the ground up with cross-browser support in mind, avoiding modern features like SharedArrayBuffer."
Link: https://sandpack.codesandbox.io/docs/resources/faq#how-does-...So now we've got an escape hatch for Node.js not having to implement modern APIs because software like this implements its runtime for the browser, and also this same software removes pressure on browser vendors bringing their implementations up to webstandard specifications by "... avoiding modern features".
While this is _technically_ cool I feel like it's a lose-lose for the overall ecosystem.
I've been a full time JS full stack dev for maybe 8 years, and this sentence doesn't make any sense to me.
Finally.
(I’m actually kidding and don’t know anything about this project nor use cases. Just thought this was funny)
The benefit is that you can use a web editor with the same dev tools (TypeScript, Babel, vite, webpack, etc) without a server VM. That saves them a lot of money in cloud instances, and speeds up things for the end user.
Other than that a posible niche use case is to emulate a full-stack for prototyping or testing purposes.
However, the complexity of this innovation just makes me want to scream into the void. I don't want to touch the frontend toolchain at all, anymore. The layers of abstraction is seriously hurting my brain.
Shoebot is not dead (even if it is getting a bit old), currently working on a new release to sort out a bunch of the tech debt.
https://github.com/shoebot/shoebot
For those into Nodebox1, on the Mac, Karsten's fork is active.
https://github.com/karstenw/nodebox-pyobjc
Plot device is a fork that went in a different direction
https://github.com/plotdevice/plotdevice
EDIT: I should also mention drawbot, the progenitor for all of these is pretty alive these days using a Skia backend
FYI, stackblitz released something similar called web container.
I suppose lessening the curl2bashness of many frontend dev tools is also an advantage.
I always like to track their progress and this too is impressive, useful work.
My respect for this company runs so deep that I at one point considered approaching them to acquire my own company.
import React from 'react'; import { UsersService } from './users.service'; import { registerRoute } from 'react-backend-router';
export class UsersController extends React.Component {
constructor(props) { super(props);
this.state = {
createUserPayload: null,
updateUserPayload: null
}
this.createUser = this.createUser.bind(this);
this.updateUser = this.updateUser.bind(this);
}
componentDidMount() {
registerRoute({
path: '/users',
method: 'POST',
handler: this.createUser
});
registerRoute({
path: '/users',
method: 'PUT',
handler: this.updateUser
});
}
createUser() {
const { req } = this.props;
const { body } = req;
this.setState({
createUserPayload: { name: body.name }
});
}
updateUser() {
const { req } = this.props;
const { body } = req;
this.setState({
updateUserPayload: { name: body.name }
});
}render() { const { createUserPayload, updateUserPayload } = this.state;
return (
<UsersService
create={createUserPayload}
update={updateUserPayload}
/>
)
}
}