dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.65k stars 10.07k forks source link

[Announcement] Obsoleting Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices #12890

Closed danroth27 closed 3 years ago

danroth27 commented 5 years ago

ASP.NET Core supports integration with various single-page app (SPA) frameworks, including Angular, React, and React + Redux. Initially integration with these frameworks was accomplished with ASP.NET Core specific components that handled scenarios like server-side prerendering and integration with webpack. But as time went on, industry standards changed and the SPA frameworks each released their own standard command-line interfaces (e.g., Angular CLI, create-react-app).

When ASP.NET Core 2.1 was released in May 2018, we responded to the change in standards by providing a newer and simpler way to integrate with the SPA frameworks' own toolchains. This new integration mechanism exists in the package Microsoft.AspNetCore.SpaServices.Extensions and remains the basis of our Angular and React project templates since ASP.NET Core 2.1.

To clarify that the older ASP.NET Core specific components are not relevant or recommended, we are now officially obsoleting the pre-2.1 integration mechanism and marking the supporting NPM packages as deprecated.

The contents of the following NuGet packages have all been unnecessary since ASP.NET Core 2.1, and so are now being marked as obsolete:

For the same reason, the following NPM modules are being marked as deprecated:

These packages will later be removed in .NET 5. If you are using these packages, please update your apps to use the functionality in Microsoft.AspNetCore.SpaServices.Extensions instead along with the functionality provided by the SPA frameworks you are using. To enable features like server-side prerendering and hot module reload please refer to the documentation for the corresponding SPA frameworks. The functionality in Microsoft.AspNetCore.SpaServices.Extensions is not obsolete and will continue to be supported.

rjgotten commented 5 years ago

@markalroberts For me, when upgrading to 3.0 from 2.2, and ignoring the obsolete warning I get another problem - the time taken to get the hot update went from being instantaneous on 2.2 to being tens of seconds, even minutes.

Really odd - the output window shows that VS has compiled the change straight away, but the client doesn't request it. Frustrating - will have to keep on 2.2 for now - anyone else seen this?

I wonder if that is somehow related to https://github.com/aspnet/JavaScriptServices/blob/master/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack/src/WebpackDevMiddleware.ts#L158

poganytamas commented 5 years ago

There is a great start / workaround having HMR back, but still not as smooth as the old solution: https://github.com/TrilonIO/aspnetcore-Vue-starter/issues/138#issuecomment-542686499

rjgotten commented 5 years ago

@poganytamastsys It's honestly not great at all. What that solution does is basic cold reloading of the entire page, whenever any one file served by its live reload middleware changes.

It's a far, far cry from proper hot reloading. It basically just automates pressing F5.

cjblomqvist commented 5 years ago

I have to agree with many of the previous comments. This feels like a bad move. I can understand the removal of some less general and less used features, but to deprecate the whole things doesn't really sit good with me - in particular the base functionality of interop with Node (NodeServices).

I think this is a big blow to the (new) MS reputation among web devs. MS is famous for long term support and for listening to what's actually used. Now it feels like Blazor is the future MS wants, but it really isn't a replacement and it'll be years before we can tell if it really meets all the criterias. I honestly feel a little bit cheated.

Let's pray that the community can pick it up (I unfortunately don't have the resources). I'm not keeping my hopes up though :/

johnnyoshika commented 5 years ago

I also use NodeServices to call arbitrary JavaScript code and I find it extremely useful. There have been murmurs about spinning NodeServices into a community driven project, but I didn't see anything official. Has anyone taken this on? If not, I'd be willing to do it, but I've never published packages on NuGet before, so I'll need some help. I also like @poke's suggestion that we use git filter-branch to extract the original history. @poke, would you be willing to help with that part?

@danroth27 @SteveSandersonMS You've both offered your help to spin this off. Assuming no one else has, how can we get started?

danroth27 commented 5 years ago

@johnnyoshika Yes, we'd be more than happy to help you get started! We can also help get you setup with support from the .NET Foundation. I'll reach out to you on Twitter so that we can discuss further.

drdamour commented 5 years ago

this doesn't make sense to me. the CLI stuff is fun and all until an app grows beyond the toddler stage.

when are we getting an updated https://docs.microsoft.com/en-us/aspnet/core/client-side/spa-services?view=aspnetcore-3.0 for the new way to do things?

johnrom commented 5 years ago

Hi all, just wanted to chime in here. I've had significant success using these packages as an SSR solution. The benefits of a middleware-based solution for SSR have merit, because they allow an app to preload all necessary information before hitting the node server, instead of hitting the node server which then requests data from various http endpoints and causes a cascade of http requests. I don't disagree that maintaining a solution which hand-holds various framework-based scenarios is un-maintainable for the future, but I think finding a framework-agnostic IPC solution for node apps is maintainable.

If we can get back to a simple package which provides an in-process and proxy-based IPC for node with pre-loaded data, I'd be happy. This IPC is not so easily available in any other web platform I've found.

rui-ktei commented 5 years ago

We also use INodeService to invoke Node function. Why? Because in our case we want to manipulate raw JSON string and we need some important functions from lodash, though our service is written in C#. I don't know why you're deprecating NodeService package; I almost feel offended by this rude and inconsiderate decision actually.

rui-ktei commented 5 years ago

And also, why NodeServices is under AspNetCore namespace to begin with? I feel this really makes no sense. Let's say I'm building a CLI (Console app) and want to invoke some JS functions, why the heck do I have to introduce AspNetCore to my project??

rui-ktei commented 5 years ago

@danroth27 My team uses NodeServices for some backend work. Only having Spa extensions means you're dumping the support for all the backend support for interaction between csharp and node? That's not thoughtful at all.

johnnyoshika commented 5 years ago

@rui-ktei I'm working with the Microsoft team to spin NodeServices into a community project. This seems like an important library for you and I could use some help. Are you willing to help?

StragaSevera commented 5 years ago

I was fond of UseWebpackDevMiddleware, and it would be very sad to see it vanish into oblivion.

GGAlanSmithee commented 5 years ago

@johnnyoshika where does this project reside? What kind of help are you looking for?

rui-ktei commented 5 years ago

@johnnyoshika , has this started already? I'd like to have a look and what kind of help are you looking for?

johnnyoshika commented 5 years ago

@GGAlanSmithee and @rui-ktei I'm still in the process of getting things set up. In terms of help, I don't know what I don't know yet. :-) I'll reach out to you soon. Thanks for expressing interest in helping.

blushingpenguin commented 5 years ago

I'm also interested in helping out with this

knuxbbs commented 5 years ago

Why don't merge parts of the Microsoft.AspNetCore.NodeServices source into Edge.js project?

There is no way to join efforts?

rjgotten commented 5 years ago

There is no way to join efforts?

They operate on two fundamentally different principles. NodeServices works by RPC-ing JavaScript written as JavaScript using JavaScript tooling. It contains glue code for both sides to build the RPC interface and from there both sides of the pond write just their own flavor of code.

Edge.js works primarily by evaling small strings of JavaScript in place in C# and small strings of C# in place in JavaScript. Without any offense meant, that kind of API is interesting from a tech demo point of view but little more. The fact that Edge.js avoids RPC to separate processes is rather nice, but on the other hand having the processes separate allows for better error recovery as well. So that's a bit of a toss-up.

PhotoAtomic commented 5 years ago

i'm also interested in collaborate to bring on this package that i consider quite an important cornerstone: how to get involved?

InvincibleDRT commented 5 years ago

I'm also interested in contributing to this project.

Grandizer commented 5 years ago

I am not sure if I can help, but I am totally interested in the result! Thanks everyone.

hheexx commented 5 years ago

@danroth27 @SteveSandersonMS SSR(Angular) is no longer supported as it requires NodeServices. Right?

johnnyoshika commented 5 years ago

Thanks everyone! I'm currently in the process of extracting NodeServices from AspNetCore and cleaning things up. Once the dust has settled, I'll circle back the this group. So far these people have expressed interest in helping:

@GGAlanSmithee @rui-ktei @PhotoAtomic @InvincibleDRT @Grandizer

chamikasandamal commented 5 years ago

Happy to contribute. @johnnyoshika : include me as well

hiyelbaz commented 5 years ago

For those who just need an in-proc v8 engine: https://github.com/microsoft/ClearScript/issues/9#issuecomment-545536190

johnnyoshika commented 5 years ago

@GGAlanSmithee @rui-ktei @PhotoAtomic @InvincibleDRT @Grandizer @chamikasandamal

I tagged you in this issue: https://github.com/koopla/NodeServices/issues/4

Let's continue our discussion there and spin this off into a community project. :-)

Daniel15 commented 5 years ago

Another approach for running JavaScript via C# is to use an embedded JavaScript engine, like V8 (via ClearScript) or ChakraCore. That's what I did for ReactJS.NET. In that case though, you don't get anything Node-specific (eg. CommonJS modules), but it works well enough if you can build your JS into a bundle using Webpack.

rjgotten commented 5 years ago

it works well enough if you can build your JS into a bundle using Webpack

The point is that many people are using the support for UseWebpackDevMiddleware to do exactly that, but also have transparent on-the-fly bundle rebuilding ready to load with a simple F5 refresh, or even full on hot-module-reloading (HMR) to swap out individual modules with updated code in-vivo; in an already running JS application.

There's no decent way to get that without some form of Webpack compiler running in watch mode; and that requires Node.js -- not just CommonJS module support; but all of the APIs such as the file-system ones; stream IO; http(s); etc. that Node.js brings with it.

JeremyTCD commented 5 years ago

@johnnyoshika

We built an INodeServices alternative a year and a half ago, Jering.Javascript.NodeJS. It's slightly more flexible - you can invoke from a stream, a string or the NodeJS cache. Also it's ~16% faster than INodeServices.

We've been using it for awhile now, so it's pretty stable. I'd suggest using it/building on top of it rather than starting a new project.

johnnyoshika commented 5 years ago

@JeremyTCD That's very interesting. I had never heard of your NodeJS. Is there anything that NodeServices can do that NodeJS can't?

johnrom commented 5 years ago

From the initial glance, it looks like NodeJS could be implemented overtop the INodeServices interfaces. Was there a specific barrier to having it done that way? In my opinion, I'd wonder how we could improve and extend the INodeServices interface in order to allow the project above to just be an implementation overtop of it.

JeremyTCD commented 5 years ago

@johnnyoshika

We left one NodeServices feature out, NodeServicesOptions.WatchFileExtensions. Am open to adding it if there is any interest.

@johnrom

Functionally, the main difference between the two libraries is that INodeJSService allows you to invoke in-memory Javascript (stream, string or cache). We felt the most idiomatic way to expose this extra functionality was with the following interface:

I suppose we could have added members to INodeService instead. This is INodeService now:

We could add those members to INodeJSService:

INodeJSService.InvokeFromFileAsync<T> is analogous to INodeService.InvokeAsync<T> and INodeService.InvokeExportAsync<T>, so this addition is straightforward as far as underlying logic is concerned. If you'd like to continue this discussion feel free to open an issue over at Jering.Javascript.NodeJS.

johnnyoshika commented 5 years ago

@JeremyTCD I just tested Jering.Javascript.NodeJS and it works as advertised. I first tried it with .Net Core 2.2 but ran into errors. With .Net Core 3, it works well.

I noticed this prerequisite though:

NodeJS must be installed and node.exe's directory must be added to the Path environment variable.

Is that prerequisite unique to Jering.Javascript.NodeJS or was that the case with Microsoft's NodeServices as well?

JeremyTCD commented 5 years ago

@johnnyoshika Created a netcoreapp2.2 console app invoking INodeJSService, works fine: repository. Tests pass when targeting netcoreapp2.2 too. Would be cool if you could open an issue with details on the errors your ran into.

Wrt installing Node.js, yes it was the case with INodeService as well. Both these libraries spin up Node.js processes.

johnnyoshika commented 5 years ago

@JeremyTCD Sorry, I wrote .Net Core 2.2 but I meant .Net Core 2.1. I created an issue here: https://github.com/JeringTech/Javascript.NodeJS/issues/50

So it seems like NodeJSService can do everything that Microsoft's NodeServices can without any drawbacks. I'll circle back to the Microsoft team to see if they can identify something that we missed. If not, I agree that it doesn't make sense to spin off another project.

johnrom commented 5 years ago

I have some concern about migrating existing apps between the two, but I'll trust in the community's judgment. The question remains: What about SpaServices? Someone will have to spin off SpaServices to use either a migrated INodeServices or switch it to use INodeJSServices.

rjgotten commented 5 years ago

The question remains: What about SpaServices? Someone will have to spin off SpaServices to use either a migrated INodeServices or switch it to use INodeJSServices.

Yes. Bare minimum being the open ended UseWebpackDevMiddleware with freely configurable Webpack instance. That scenario is not supported by Microsoft's new solution, which only covers React and Angular apps built via their respective dedicated CLI tools.

And then there's still the pre-rendering support left to cover.


Concerning the basic webpack middleware: I've already taken a fork of the code that forms the aspnet-webpack NPM package. This package contains the Node.js side of the code to glue the AspNetCore UseWebpackDevMiddleware to the official Webpack dev middleware.

I had to do so to fix support for Webpack's multi-compiler mode, which Microsoft didn't implement correctly. You're supposed to pass an array of configurations to a single webpack compiler and register a single dev middleware that uses that single compiler. Instead, Microsoft creates fully separate Webpack compilers for each config in the array and registers fully separate middlewares. It breaks a few things HMR related and may affect other stuff.

The code for this package is generally a mess -- Note the remarks I wrote earlier -- but it also looks like it wasn't touched for years and everything from toolchain to dependencies is woefully outdated. (It's even loading a Promise polyfill for NodeJS. That's how old and outdated it is.)

While I can clean it all up and fix among other things the multi-compiler mode -- There's more wrong. Again: note earlier remarks. -- I don't have the resources to maintain this long term, so I'd need to transfer it to another party. Ideally, whichever party is going to take up SpaServices maintenance.

Frozenthia commented 5 years ago

Can someone, preferably someone from Microsoft, explain to me the general process of offloading a package and library to the public? Would the namespace/package name/package history remain the same? Could we still prefix it with Microsoft to sort of have a de facto standard as it stemmed from Microsoft? Would Microsoft host the repo or no? I kind of have concerns about a fractured community with 20 different variations, and one of the ways I can choose a package is to see what has the most community support, most downloads, etc. A fractured set of Spa/Node libraries sounds iffy. Has this ever happened before? I'd just like to know what to expect.

danroth27 commented 5 years ago

@Frozenthia

Would the namespace/package name/package history remain the same? Could we still prefix it with Microsoft to sort of have a de facto standard as it stemmed from Microsoft? > Would Microsoft host the repo or no?

Since the package would no longer be shipped by Microsoft the namespace and package ID should change to align with the community project. The community project would be hosted in its own org and repo separate from Microsoft, but can still be part of the .NET Foundation.

I kind of have concerns about a fractured community with 20 different variations, and one of the ways I can choose a package is to see what has the most community support, most downloads, etc. A fractured set of Spa/Node libraries sounds iffy. Has this ever happened before? I'd just like to know what to expect.

This is certainly a valid concern. Fostering a community culture of supporting existing projects when appropriate is one way to address this. At the same time, we should welcome new innovative projects that take a fresh approach and provide choice and options. It's a bit of a balancing act.

GGAlanSmithee commented 5 years ago

At the same time, we should welcome new innovative projects that take a fresh approach and provide choice and options.

@danroth27 I agree that this is generally a good thing, but for anyone who was a victim of the npm package tsunami of 2016-ish, this balancing act isn't very attractive. Having a single, by Microsoft, blessed alternative is a must IMO (and my interpretation of your statement tells me you agree)

Also, I (from my own experience) think that developers have different expectations when it comes to .NET / C# / MS than for example NodeJS. We do not expect to have to rely on third party packages. Of course, there will always be those, but the majority of the code will be .NET. This is neither good or bad, but it's more or less a de-facto contract (IMO) that shouldn't be broken without a good reason.

prcdpr commented 5 years ago

In my company we were also using Microsoft.AspNetCore.NodeServices for calling JS functions via InvokeAsync and now after upgrading to .NET Core 3.0 it became obsolete without alternative other than forking source code.

anterokarttunen commented 5 years ago

Does this mean that i have to stick to .NET Core 2.2 forever? omfg......

Did not find out from migration guide how to migrate these ( https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio )

                // Webpack initialization with hot-reload does not work in 3.0 -.-
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true,
                });

EDIT: I can definately say that things like these can ruin .NET Core.. where is the trust ????

johnnyoshika commented 5 years ago

Does this mean that i have to stick to .NET Core 2.2 forever? omfg......

No, you can use NodeServices in .Net Core 3, but you'll get a deprecation warning:

image

johnnyoshika commented 5 years ago

@JeremyTCD and all:

I discussed the future of NodeServices with the Microsoft team and we decided that the best path is to offer a community supported NodeServices as a drop-in replacement for existing users (using the namespace Koopla.NodeServices). Koopla.NodeServices will only support bug fixes and will recommend new users to use JeringTech/Javascript.NodeJS. Any feature enhancements will also be redirected to JeringTech/Javascript.NodeJS. I think this provides the best balance between supporting existing users of NodeServices while allowing JeringTech/Javascript.NodeJS to be the future of .Net / Node integration.

Please let me know your thoughts.

JeremyTCD commented 5 years ago

@johnnyoshika I can see why some might prefer an INodeServices clone over Jering.Javascript.NodeJS. Their systems are after all, running just fine with INodeServices.

At the same time it would be inefficient to duplicate enhancements made to Jering.Javascript.NodeJS in an INodeServices clone.

Considering all that your plan seems sensible to me.

To give users clarity on how the projects are related, I'll maintain a simple list of feature differences in both their ReadMes.

anterokarttunen commented 5 years ago

Does this mean that i have to stick to .NET Core 2.2 forever? omfg......

No, you can use NodeServices in .Net Core 3, but you'll get a deprecation warning:

image

Thanks, sorry for being bit dramatic ( I got angularjs 1 -> 2 flashback )

And also noticed that I was missing ( because of project restructure ) both Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.SpaServices.Extensions

Having these fixed the issue and I should be able to use dotnet core 3 yay.

image

One more thing, if microsoft is really going to remove

1)

                // Webpack initialization with hot-reload.
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true,
                });

2)

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });

Also can microsoft write guide later on ( when you actually obsolete these), how to migrate these two parts ( WebpackDevMiddleware* + hotmodulereplacement and app.UseMvc + MapSpaFallbackRoute into whatever the new classes, methods or configurations will be?

EDIT: I didn't try to use this:

serviceCollection.AddNodeServices()

Would it automatically configure 1) and 2) ?

anterokarttunen commented 5 years ago

Final question, are these changes made because things can be simplified to single "enabler methods" like

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.EnableWebpackDevMiddleware(); }

I like net core very much but if you compare it to spring boot, you need to catch up a bit ( spring boot has plenty of awesome stuff which net core should also have )

schmitch commented 5 years ago

actually the biggest problem with Microsoft.AspNetCore.SpaServices.Extensions is, that some stuff is internal only, but it would be extremly useful if it would be public. i.e. everything that worked with webpack might be replaceable by a custom "framework" to build something like AngularCliMiddlewareExtensions by ourself. However what's the point if everything in this package is internal only.

bugproof commented 5 years ago

Save yourself a headache and don't mix node with c# ever again, just use dedicated SSR solutions for the js libraries/frameworks of your choice (vue - nuxtjs, react - nextjs, angular - universal, svelte - ??). To those with already existing projects - I feel your pain. My condolences.

Trying to couple two different ecosystems is just a bad idea and a hell to maintain. If you need that kind of communication just use Web sockets directly or SignalR