-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does not work in stackblitz #99
Comments
This is a native module with deep integration into operating systems. I'm not sure how it could work in a browser environment since there is not even a file system. What are you trying to do? |
I have a static site generator that rebuilds and reloads on file change. For that I am using I never expected it to work in stackblitz... but apparently stackblitz become really really good at simulating a file system and most packages seem to just work 😅 How I got the idea that it works is by looking at astros stackblitz examples. It's a static site generator that uses chokidar via vite. And it works in stackblitz. So it seems there is a way to make it work... is that something If so then I could dig a little deeper |
I'm very interested in using |
Can someone explain how deeply Stackblitz emulates the usual Node environment (and which parts)? If there are no primitives for watching file changes, it will have to use polling. |
Hey all- Eric from StackBlitz here, happy to provide some context. StackBlitz uses WebContainers (a WebAssembly-based operating system) to run Node.js inside your browser tab. This version of Node.js is pulled from Node.js core itself (w/ some minor tweaks) so it has broad support for nearly all Node.js APIs. Importantly, WebContainer includes a UNIX compliant filesystem, so all Node.js FS APIs you would expect (including synchronous operations, watching, etc) work exactly as they do on local. The main limitation of this approach is that native addons must be available as Wasm binaries otherwise they will not work. This seems to be the issue happening here for the For filesystem operations in StackBlitz/WebContainer, you can use the normal |
Thanks @EricSimons! So what would be needed is something like the existing watcher/src/shared/BruteForceBackend.hh Lines 12 to 18 in caf372c
And generally some boilerplate/a build step for an Emscripten interface as opposed to Napi will be needed. |
Does that mean that we would have to implement a completely different interface for this in JS? WASM doesn't have file system access afaict, so I'm not sure how this could be made to work. The whole point of this module is to avoid node's |
@EricSimons since you are here, I have questions. Basically, I am very confused about what a WebContainer is exactly. All of the marketing material kinda glosses over the details, and hand waves a bunch about how it works. The repo doesn't really give much more information. Is there a more technical overview available that describes the exact interface that is available and some of the implementation details?
Any details you can provide would be helpful. At the moment I really don't have any idea what a WebContainer actually is, other than some kind of magic that somehow runs Node or something like it in a browser. As we move more of Parcel away from JavaScript and more toward native Rust modules, having an understanding of this would be helpful. |
Beyond what's in the readme and the blog post not really, as it hasn't been an issue to date. I think the parcel filewatcher might be a unique case simply because it's purpose is a very specific syscall level integration, whereas other projects (like next.js/swc/etc) have implementations that are a bit higher level and/or syscall agnostic.
Lower level, largely the syscall layer where Node.js interacts with the host OS.
The shell in WebContainer exposes a lot of the usual POSIX built-ins ( For Wasm applications that need syscall access, in the near future the solution would be leveraging Node.js' implementation of WASI. We haven't enabled access to this in WebContainer due to some upcoming changes I can't speak to yet. For the time being, you can instead leverage the Node.js API surface to perform syscalls. This is similar to how emscripten compiles down to the Node.js APIs for filesystem, networking, etc.
None. WebContainer is an operating system designed to run inside a browser engine, and therefore is subject to the same limitations as any other browser context: if you want execute code from a language other than JS, it needs to be precompiled as a WASM. There has been work from Node.js core on enabling Wasm support w/ NAPI but AFAIK has not yet come to fruition. Last I heard there was interest in WASI to help bridge the syscall gaps, but it needs to be sufficiently matured before it could be viable.
Node.js is the only runtime we ship with WebContainer OOTB atm, but any language/runtime provided as a Wasm module can also run inside WebContainer today. If you have an entirely Rust-based CLI that compiles to a Wasm module, the only thing you'd need to do is wrap it with some JS code that wires it up to the interfaces it requires (command line args, fs, network, etc).
Yes, only available to JS via Node.js' fs.watch/etc until WASI support is landed.
Totally. I think the main thing is to include Wasm as a compile target alongside your existing native addons. This does require a little bit of extra work in loading those native bindings- here's how Next.js does this w/ SWC as an example. Another quick way to test if this will work for existing (and future) sandboxed Node.js environments is by passing the |
Sure, so for I suppose the benefit of including a JS wrapper here would be API compatibility, so you could use the module unmodified both natively in Node and in the browser. Perhaps there is a way to detect if native modules are supported, and if not, load the JS version? |
Yeah I think that makes sense. It looks like Next.js does a try-catch to determine if the runtime can load the native addon, and if not then loads the Wasm version. I imagine you could use the same approach here. Alternatively there might be a more static way of analyzing this... cc @d3lm who might know more on this front. |
Yeah try/catch seems fine. To be 100% transparent, I do not personally have time to work on this anytime soon. But, if someone wants to do it, please feel free to send a PR! Basically we'd expect a JS implementation of the same API exposed by the module currently, but written in JS using the Node |
Hey ya all 👋 Maybe I can chime in on some of this stuff. I think the solution that has been discussed here, a pure JS implementation that simply uses Node's
@devongovett Yep, you can use a try/catch or you leverage conditional exports. Loading a native addon will fail in WebContainer because they are disabled by default (via the new CLI option The other option would be to use conditional exports. In your
With this in place, it would use a different entry point ( In this particular case, it's recommended to treat the I would personally recommend the approach using conditional exports because it's good practice to define a clear interface that is exported as well as taking different environments into account. |
in #134 i've added support for a chokidar backend 🎊 |
There is now an alpha version of a WASM version available in the |
Thanks @devongovett you are a lifesaver! Just integrated parcel/watcher with unjs/listhen experimental watcher and this solved issue with stacklbitz (also my general concerns regarding bundling issues. FYI, we use this package for Nuxt and Nitro CLI which are zero dependency. Not yet the watcher). One question: Other than being experimental, do you know any downsides of using wasm build in Node.js environments? |
I would not recommend using it except in unsupported environments (like browsers). It is significantly less efficient than the native watcher implementations that deeply integrate with the operating system. It must recursively traverse the directory hierarchy and watch each nested directory separately, whereas most of the native implementations use operating system APIs that avoid the need for this. As an example of the difference, the Nuxt team tested their previous implementation using chokidar (which also uses node's watcher API under the hood) and the native Parcel watcher and saw startup time decrease from ~30s to 300ms nuxt/nuxt#20179 (comment). That's probably almost entirely due to not needing to walk the entire directory heirarchy, which can be avoided by using better OS APIs. So unless you're running in a browser or on an unsupported operating system, I'd keep using |
Gotcha thanks for mentioning the recursive scanning difference. (maybe docs could include this note?) For listhen, i will use try/catch fallback to unblock stackblitz and leverage full performances on local 👍🏼 As I mentioned, the main other concern is for the nuxt CLI ( |
This should now work in Stackblitz as of v2.3.0! https://stackblitz.com/edit/node-bpupxc?file=index.js |
Using
@parce/watcher
in stackblitz result in the following error.Reproduction
node server.js
in the terminalExpected
Watch works on stackblitz
The text was updated successfully, but these errors were encountered: