Closed PawelStadnicki closed 3 years ago
To debug JavaScript inside the web outputs in VS Code, you can open the command pallet and run Developer: Open Webview Developer Tools
.
I'm not aware of anyone else trying to use HMR in .NET Interactive yet but it sounds like an interesting use case. If you can't figure out what's going on and can provide a small repro, we can probably help out.
thanks @jonsequitur ! it helped me to find the root cause: I missed webpack config entry that allows to bypass more CORS actions (disableHostCheck: true).
Summarizing: HMR works with .NET interactive :) I have a PoC that translates F# to JS with Fable (via my own F# Kernel Extension) so F# code communicates between the F# and JS cells.
I wanted to achieve more that I can do with Plotly.NET I process the geojson open data in F# (F# Kernel) and visualize it with F# (but on JS/HTML kernel so I canhave full control). The visualization is based on Azure Maps, turfjs and d3js
Glad this helped!
In case it's useful for Fable as well, we're in the process of making JavaScript cells and the JavaScript kernel more like the other "server-side" kernels, programmatically. So you can do this with JavaScript:
That is very interesting, more than great in my scenario. Can't wait for it
The JavaScript kernel example I gave works right now. A possible next step here would be to have kernels like this execute entirely in the browser, which in the case of Fable might include transpilation. Would that be of interest?
I'm not sure why the mentioned sample cannot work in the browser or what we mean by running in the browser here. It is standalone website or .NET Interactive run for instance in the Codespaces?
I will describe shortly how I tackle the Fable in the .NET Interactive. Please note that my knowledge about extending .NET Interactive is fairly limited. I had at least two options:
1) Fable (standalone) Kernel. This is (probably) ideal solution because we can hide a lot of boilerplate behind the scenes like UsePackages, UseNamespaces etc. We can select Fable as a kernel from the drop down list in visual studio code so it seems to be a good UX experience. I didn't opt for that initially as it requires some knowledge which I could gain first with the second option and later apply that knowledge here if second option is not enough. In particular it is (was) hard for newcomer to modify locally both vs code and write a kernel itself. Maybe there is some good place for it in the so called "ExtensionLab" package similarly to Mermaid or SandDance but I only started to observe it recently
2) Fable as a FSharp Kernel extension. This is what I'm implementing as a PoC. This option is very easy to use as it can be loaded just with #r nuget command. The F# code is written normally inside F# kernel cell but with #!fable magic command. Command handler instead of executing the code put it on Fable Cli for transpilation (via CliWrap nuget package) and observes the results. The result is pure js bundle created with webpack (as I embrace many js libraries like turfjs, d3js, AzureMaps). Finally here I have (at least) 2 options to project my result as well: 1) context.Display where my bundled js is put to ScriptContent. The advantage is that I have my result displayed immediately and just below the F# code, the downside is that HMR doesn't work in this case as in order to update my code I have to rerun the cell which displays everything from scratch 2) put the bundled js into the html kernel/cell. Here html cell is not updated with F#/Fable execution on following runs so HMR works (the content is in fact updated by webpack-dev-server under the cover). The downside is that I have to have additional html cell which I have to fill manually
So I'm still looking for best experience. Do you see any issues that may come over with Github Codespaces usage here ? I don't have access to the preview so can't verify it.
My work is going to be 100% open source, probably need one more weekend to finish the PoC and publish it
I'm not sure why the mentioned sample cannot work in the browser or what we mean by running in the browser here. It is standalone website or .NET Interactive run for instance in the Codespaces?
.NET Interactive works today in CodeSpaces. Code execution still happens on the server in that case.
What we mean by execution in the browser (and I guess it would be clearer to say frontend, since this also applies to VS Code) is a little different. It would be like a single-page architecture, where the kernel code of JavaScript that's loaded statically, after which point there's no communication with a server needed to execute notebook cells.
We can select Fable as a kernel from the drop down list in visual studio code so it seems to be a good UX experience. I didn't opt for that initially as it requires some knowledge which I could gain first with the second option and later apply that knowledge here if second option is not enough.
We're hoping that eventually the kernel can provide the information dynamically to the frontend so that no VS Code extension modifications will be needed to bring in additional languages, and the work can be done entirely in the custom kernel.
A few general thoughts, not guaranteed to be useful:
The architecture you're describing is similar to what we've discussed for a Try .NET kernel. The idea there is that some parts execute on the server (e.g. completions, hover text) and other parts in the frontend (browser or VS Code). We've even discussed the possibility that inheriting from CSharpKernel
and overriding HandleAsync(SubmitCode, InvocationContext)
could work. In this approach, the overridden SubmitCode
handling, instead of executing the code, would return a compiled assembly to the frontend, which would run it using Blazor WebAssembly. The server-side kernel could aggregate the compiled state, allowing completions to work, or it could potentially be round-tripped by the frontend kernel if you want a stateless server.
Making it a separate kernel instead of a magic command means it won't share state with the "other" F# kernel, which might make it easier to add functionality over time. Ultimately, implementing a kernel is possibly easier than implementing a magic command anyway. But I get that the VS Code extension part makes the magic command nicer for now because of code coloring and other editor features.
Another thing to consider is that sending commands to the JavaScriptKernel
as in my screen shot above is more "correct" than using Display
and ScriptContent
, because that way, the server-side code can await the result of the computation that ran in the frontend, respond to failures, etc., and the user will see better errors and so on.
We're hoping that eventually the kernel can provide the information dynamically to the frontend
I think that indeed would be much needed. VS Code is a one story, the second is that I expect many developers to write custom extensions/kernels for blogging, education and other creative ways
which would run it using Blazor WebAssembly.
I'm interested with Blazor as well but I'm leaving it for the coming months. From one hand Fable/F# is build around js ecosystem and it works very well. From the other hand Blazor is/will be very supported from MS and well adopted, I assume the Try.NET / Try.js will use it. I don't need anything specifically from Blazor except ASP.NET hosting which I could get for free in that case. But who knows, maybe I will have some performance reason to use some port of F# on WASM where Fable still has no focus right now (they experiment with sveltejs )
Another thing to consider is that sending commands to the
JavaScriptKernel
as in my screen shot above is more "correct" than usingDisplay
andScriptContent
Agree, I will try that
Making it a separate kernel instead of a magic command means it won't share state with the "other" F# kernel,
hmm,why? Actually I do not use F# kernel directly in my magic command , just take the code from SubmitCode command and put it into fable cli. If I created it as a kernel rather than magic command why I wouldn't have coloring end editor facilities ? I assume my FableKernel could just inherit/extend the F# Kernel but maybe you mean some additional work from the frontend side (vscode or any other Monaco Editor page) is required for that.
If I created it as a kernel rather than magic command why I wouldn't have coloring end editor facilities ? I assume my FableKernel could just inherit/extend the F# Kernel but maybe you mean some additional work from the frontend side (vscode or any other Monaco Editor page) is required for that.
This is because aspects of the VS Code experience are driven by the VS Code extension's view of what language a cell is. This includes code coloring, commenting, and other language-specific features provided by VS Code.
I have pretty advanced application in .NET Interactive so to speed up the experiments I wanted to use HMR but it doesn't work (at least for me).
Applying HMR to .NET interactive may seems to be exaggeration because such an experiments are rather short in nature but believe me that I have a reason for that :)
In simplification: I'm doing some advanced JS in one VS Code cell, under the cover I bundle it with webpack and put final content into HTML kernel. It works great except HMR. I need to execute HTML cell (like full reload) to have it affected.
My HTML cell is more or less like this:
When I extract exactly the same html markup and put it to some index.html file, HMR works like a charm and I can see everything in chrome dev tools.
Are there any internals that may block HMR in .NET Interactive? Is there any way to see logs why it may not work ( I do not see anything special in VS Code output window)?