-
-
Notifications
You must be signed in to change notification settings - Fork 733
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
Taking it to the Next Level! #872
Comments
Yeah that sounds super awesome and goes in the direction (but honestly already quite a lot further) what I had originally in mind. So you definitely have my blessing! |
How about setting up a new branch for this, like nextgen or so? My typical approach for such things is to "race" over all the tough points to get to a point where I got it roughly working - at least enough for me to know that it's doable. That phase is already done, so we're not talking just about ideas, but most of the core points are already confrimed and kind-of working. I'll follow-up with a few posts, showing what I got working already and how, so that we can discuss things rather than me just dictating the result. Sounds good? |
At first glance, I really like it too! It would be exciting to see if everything works when it's in use... |
I'm starting a series of posts, documenting and explaining the changes I've made so far, Let's start with this: .NET Project System Extension & Manifest ReplacementIn the screenshot above you can see an "Electron.NET" section. This is made possible through extensibility of the .NET/VS project system. It is working without the need for developing a Visual Studio extension like in case of the older project system. It is working working through the nuget package. So that part doesn't change: You add the Electron.NET nuget package to an ASP.Net Core project just like usual. There's also no requirement to use Visual Studio, but if you do, you get this nice UI tab in the project designer as shown above. That's essentially the same plus a little bit more than what is currently in
The very first building block now, is to automatically generate a package.json file (for the Electron app) at design time. Here you can see it being updated automatically while editing the values in the app designer: ElectronNet_PackageJson.mp4 |
BuildingPrerequisitesRID-Specific BuildsSince we always end up having RID-specific output, we can do so right away, even when not publishing. This allows pinpointing platform-specific issues early (like unsupported APIs), but most importantly, it allows a clean separation of outputs, because the RID gets included in the output paths when specificed (this happens automatically by the build system). To make this more explicit, I've added a selection - which also enforces that one is specified (if not using VS, there's still one set as default). Now we get output paths like this: This allows to have a separate Windows and a Linux output (like for running on WSL) without conflicting. Unpackaged App LayoutFor running and debugging, we also need the Electron part. This is platform-specific as well (at least when using Electron), so this part should go together with the output under the same folder. For simplicity and avoiding ambiguities, I'm using a dotted subfolder at the moment: So, the full output tree looks like this: Populating the
|
Incremental Build DemoNote that "Building Electron" here means to copy (update) the changed files and run ElectronNet_Building.mp4 |
One challenge I see here, which is why I didn't make it freely selectable by design in the past. For example, there are many breaking changes between the native Electron versions. Events are called something different, functions have been removed, different data structures, etc. It would be interesting to know how you can stabilize this here? |
For support native Electron extensions, we have integrated a feature, called Electron Hooks, typically require an Electron CLI again. This is because it manages triggering actions like "npm install," starting TypeScript, etc. However, this might also work via MSBuild?! |
Yes, I've seen your earlier comments in this direction. Yet I've seen that people are using more recent Electron versions with ElectronNet and there's currently 30.0.3 in the devlop branch vs. 23.2.0 in the main branch, plus an open PR for switching to 31. This makes me assume that these newer Electron versions are at least partially tested by users. Currently in Electron.NET, it's hard to change the preconfigured version. Of course this has the advantage of keeping everybody on the safe side, but it has also prevented most users from trying different versions, so there's little to no feedback about compatibility with newer versions except those PRs to the develop branch. My thought is that allowing to switch the version freely will bring more feedback and possibly also PRs from users with appropriate fixes. Since there's UI now to switch the version, it would also be possible to show a warning ("unsupported/untested") when selecting any other version than 23.x.x - until others are confirmed working.
Generally, I see two approaches for this: Writing Integration TestsOther than unit tests (which might not help much for this), integration tests would mean to create a test app and run coded tests for the various APIs in the context of the running app. Autogeneration of Electron API ProjectionThis would be a bit more advanced, but I've done something very similar before. Electron.NET is just a small puzzle piece for us for covering Linux platforms. We have a kind of cross-platform meta-framework which allows us to bring the same app to many platforms. It works on top of various other frameworks, namely WinUI3, UWP (xbox), MAUI and Electron.NET (plus generic web), using always the same html/js core code but extended by many platform-specific features done in C# (a shared base, plus platform-specific C# with P/Invoke etc. and a range of plugins). Just that you know about the background of where I'm coming from. So, a similar autogeneration would also be possible here. Since TypeScrip declarations are available for Electron, this also wouldn't need to end up having object as parameter and return types. Once it's auto-generated, you can easily generate this for every major Electron version. But I'm not sure whether I got that much time to spend, so probably aim for a simpler solution first. :-) |
I haven't forgotten that part, but here I'm not sure yet about the way. I see these two options:
I'll look into feasibility of the second approach, when it doesn't work nicely, the former approach should always do it. Either way it's clear this this should work just like before. |
ElectronHostHookThat part was a bit mind-bending to figure it out. Not about how to handle it but rather about understanding the way how it's done and how it rather should be done, because the current approach is - err - not quite by the books. Now I understand that this was also done in order to perform TypeScript compilation of a custom The SolutionOkay - so what we need is just a single npm install as it's all a single node.js application. But the When we run In turn, we are creating a correct app config and we need to run The best part: nobody with a custom host hook will need to change anything. Additional NotesElectron Types in HostHookindex.ts and connector.ts are currently using Electron.App in their constructors. This is not valid because the host hook package.json doesn't import Electron as a dependency. And I don't think it should, because this would just blow up everything and it's purely a design-time thing - the generated js files don't have typing anyway. (in the development solution it doesn't error because it is imported elsewhere and Intellisense adds all dependencies to a common pool, but for Electron.NET consumers, these errors do show up - have seen it as well) Package DietAll generated packages will become 30 MB smaller in size. That's because all packages currently are including the TypeScript dev dependency package which isn't actually needed: |
Host Hook is all good now. I've changed the first post into a task list for tracking progress. Next point is: DebuggingI belive this is a point where many interested developers have turned around, looking for other possible options. The current behavior is indeed somewhat hard to sell: normally in ASP.NET projects, you can easily work and debug the project, but when they come to try Electron.NET and start debugging, they realize that debugging doesn't work as expected. Instead of debugging their code, the debugger is debugging an Electron process where there's nothing interesting to see with a managed code debugger: There just isn't any managed code running in Electron/Chromium processes. And then - well, you can of course attach to the ASP.NET process (with the new "Re-attach to process" feature in VS, this has become a bit less tedious) or you can add Launch SequenceIn order to debug the ASP.NET project, we need to have the debugger launch it directly. VS has the ability to debug multiple processes in parallel, but - unfortunately - not from a single project. Setting up an additional project just for debugging is possible but ugly and complicated. The only way to get what is needed here is to have the debugger launch the ASP.NET project and let the ASP.NET project then launch the Electron app. But we can't easily change this for packaged applications. Since this is all Electron, they are relying on the Electron app to be started first and I don't think it's reasonable to change this. Long story short: both ways are needed!
Launching ASP.NET FirstPretty much straightforward, just the other way round:
Debug Launch ProfilesSo that's the result: The Electron (unpacked) profile launches Electron and the other one the ASP.NET project for debugging. I'm getting tired of writing - time for another demo! |
Yea, well - when something sounds like too good to be true, it's hardly ever true. Exceptions are rare, talk is cheap - time for truth 🚀 Debugging Demo Pt 1ElectronNet_Debugging_1.mp4Debugging Demo Pt 2ElectronNet_Debugging_2.mp4 |
I love it! I think we should go that path. Regarding selecting an Electron version; my idea was to have an adapter here - something like (names just to illustrate the idea)
Bridge implements Api, Core references / knows Api. One selects a version, which installs / uses a variant of Bridge that is compatible with the Electron version. This way Electron.NET is "independent" (to some degree) on Electron. My idea was to start with a single / or two (at most) of the most popular Electron versions for the Bridge. Most of the time - as already written - a new Bridge / support for a new Electron version is really easy to establish. This could also be backwards compatible, i.e., if Api gets a new feature that is only there in a new version of Electron, then older Bridges might still implement it as a stub / just to be compatible. |
Hi Florian, this sounds very good to me - especially because this fits together pretty nicely as it's something that I'm not able to cover, not even having good ideas for - same like many other things |
I haven't tried to fully ingest your idea, so what I'm saying is more from general consideration: I think I' should also build and look at some diffs of Electron APIs from version to version to get a feeling about what we're talking here. My personal preference when it comes to such things like APIs or other subjects of versioning management and adaption is automation in whichever form may be applicable, be it auto-generation, auto-parsing, both, or else. Circling back to Electron.NET. It's a great project, there's not really anything like it, but there's a substantial stagnation of interest since 2023. I don't think there's much to wonder about the predominant reason for that: It's outdated and appears to be somewhat / somewhat-not abandoned, yet at least not under active development. It doesn't matter to people whether Electron 23 is still a good choice, they want to see progress and activity to gain sufficient confidence to go with it. In the most extreme case: Even when it's the same package for several years and it only gets released regularly with new version numbers - that's still a night+day difference (for the better). And that's where automation can turn things upside down for good. I don't have anything specific in mind. I also don't have an understanding yet of what or how it could be and what's possible. Maybe not fully but at least partially automatied, so that it takes just a few hours of manual work for releasing a new version. Summing Up The above is probably a bit extreme and overdriven - my original thought I wanted to express is that whichever model for API verionsing and compatibility we would choose, it shouldn't too much depend on individual/manual work, because this will always cause stalls in progress - just naturallly - we're' all shifting focus here or there over time. |
I actually wanted to keep this for tomorrow, but I'm so excited to share it with you - can't hold it back... WSL/Linux DemoElectronNet_WSL_Debugging.mp4 |
Yea, this would lead to a correct result, but it would also put quite some burden on us to maintain it over time. API DecorationThe basis would be that we implement the Electron API as a UNION across versions, means: "Everything from Electron 23 to 34". We could add the following to our .net API:
Then we can use those attributes to decorate everything in our API:
For the (hopefully rare) cases of truly breaking changes (like incompatible method signatures, where parameters change and don't just get appended), we can add compatibility members. For example: class ApiClassOne
{
[ElectronVersionFrom(V30)]
[ElectronVersionNote(V23, V30, "Breaking change in V30, for targeting earlier versions, use DoSomethingBeforeV30")]
public void DoSomething(int param1, string param2) {
...
}
[ElectronVersionUntil(V29)]
public void DoSomethingBeforeV30(string param1) {
...
}
} When parameters are just added, we can add them as optional (with default null) like this: class ApiClassOne
{
public void DoSomething(int param1, string param2, [ElectronVersionFrom(V30)] string param3 = null) {
...
}
} .NET AnalyzerFinally, we could create an "Analyzer" dll. This would need to be implemented just once and will never need to be updated. We can get inspiration for how it's done from the Xamarin code. Semi-Automated Version MaintenanceThis would allow us to automate large parts of maintenance when new Electron versions are released:
As we don't have any commitment to provide full coverage of Electron APIs anway, I would expect that quite often there's no manual intervention needed at all and we can just press a button to release a new Electron.NET nuget package version. What do you think about this? |
By including all kinds of APIs you will force to have a new release of the main package, which, naturally requires more resource (e.g., more testing). Also, if we ship all APIs in a single API then you will incl. unnecessary bloat in "your" (i.e., Electron.NET end-users) codebase, too. The adapter pattern could be cheaper / at most as much effort imho, as the API is abstracted away. The specific adapters could be auto-generated, too. |
Yea, it was just an idea, if you think that yours will cause less effort, then that's the way to go of course. What I'm wondering...do you actually know an Electron API in Electron 33 or 34 that is incompatible with the current implementation (targeting 23)? The only thing I know is that BrowserView is deprecated (but still working).. |
No - for the API surface that we cover we should be fine. In many / most cases I also think that the difference(s) between two versions of Electron should be rather small - if any. |
I had a done a quick diff of their TypeScript definitions between 23 and 34. It's really huge, so you can't easily go through everything, but I looked at a few classes and in almost all cases, it's just additive, rarely breaking, so once we get everything canned and able to emit new versions, I'm quite confident that interest will grow again. From my side, the remaining point is publishing (packaging). I'm halfway there, though. |
Hi @FlorianRappl and @GregorBiswanger,
after reading the "Reloaded Discussion", I thought it's time for some positive vibe and try to move things forward a bit.
Before I'm going to shock you with the intentions and ideas I have, I think I should drop the magic words, saying that I'm willing to actively help in these regards rather than demanding anything. Essentially, I'm kind of forced into it, because the slow debugging startup times (and a few other limitations) are preventing me from finishing my work. Now I could do just the minimum required changes privately, but I thought it would be nice and fair to provide some return for the benefits that we gain from your project.
Proposed Changes
In the other conversation, you mentioned that you made some plans for future evolvement, so I hope this is not too far off, even though it may appear a bit radical ☢
Anway, here's what I'm up to:
Ideally also get it working like with Browser Link
This means to use a regular build (to MSIL, without publish) at the .NET side and an unpackaged configuration at the Electron side (just npm install, not invoking electron-builder)
Putting the electron files into the same subfolder path like the .net build output, e.g.
bin\net8.0\win-x64
, becausebin\Desktop
is ambiguous when building for multiple target RIDs.Only the electron build commands need to be run on WSL, the .net side can be built on Windows
Let me know what you think about it!
sw
The text was updated successfully, but these errors were encountered: