Skip to content
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

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

Open
danroth27 opened this issue Aug 5, 2019 · 175 comments

Comments

@danroth27
Copy link
Member

@danroth27 danroth27 commented Aug 5, 2019

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:

  • Microsoft.AspNetCore.SpaServices
  • Microsoft.AspNetCore.NodeServices

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

  • aspnet-angular
  • aspnet-prerendering
  • aspnet-webpack
  • aspnet-webpack-react
  • domain-task

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.

@NotMyself

This comment has been minimized.

Copy link

@NotMyself NotMyself commented Aug 6, 2019

Is UseWebpackDevMiddleware going away with this change? Or UseSpaStaticFiles?

@flcdrg

This comment has been minimized.

Copy link
Contributor

@flcdrg flcdrg commented Aug 6, 2019

We've been using Microsoft.AspNetCore.NodeServices as a way of executing JavaScript in Node on the server from .NET Core - specifically by calling the InvokeAsync method(s).

We'd previously been using the ClearScript library (in an earlier .NET Framework project), but that does not yet support .NET Core/.NET Standard.

If Microsoft.AspNetCore.NodeServices goes away, our only alternative would probably be to fork the source code.

@CodeTherapist

This comment has been minimized.

Copy link

@CodeTherapist CodeTherapist commented Aug 6, 2019

Is UseWebpackDevMiddleware going away with this change? Or UseSpaStaticFiles?

@NotMyself As far as I understand UseWebpackDevMiddleware will go away and UseSpaStaticFiles will not.

Seriously, I liked this webpack middleware with HMR, because it accelerates the inner loop and is more comfortable instead of having two processes (dev server + ASP.NET Core app). It also reflects more the production running app - that is served by ASP.NET Core using e.g. Kestrel.
I use it with vuejs (started with this obsoleted template).

I would appreciate, when useful libraries aren't become obsolete after years of supporting it. That weaknesses the trust using a library. At least, I expect a comprehensive migration guide for those who using the obsolete libraries.

@Simon-Bull

This comment has been minimized.

Copy link

@Simon-Bull Simon-Bull commented Aug 6, 2019

We use the ISpaPrerenderer.RenderToString() functionality to server render a VueJS application, passing application context with the customDataParameter.

Is there a recommended migration path to move to functionality in Microsoft.AspNetCore.SpaServices.Extensions? This seems to use RenderToString() itself.

@bugproof

This comment has been minimized.

Copy link

@bugproof bugproof commented Aug 6, 2019

Any reason why there's no official vue project template?

@CodeTherapist

This comment has been minimized.

Copy link

@CodeTherapist CodeTherapist commented Aug 6, 2019

Any reason why there's no official vue project template?

@bugproof Maintaining templates isn't effortless. This has been discussed in issue: aspnet/JavaScriptServices/issues/412.

@Sebazzz

This comment has been minimized.

Copy link

@Sebazzz Sebazzz commented Aug 6, 2019

So how would HMR work with Webpack now? Webpack runs its own web server.

@ericgreenmix

This comment has been minimized.

Copy link
Contributor

@ericgreenmix ericgreenmix commented Aug 6, 2019

My company also uses the Microsoft.AspNetCore.NodeServices to execute JS from .Net. Is there a recommended alternative, if NodeServices is going away?

@alexdresko

This comment has been minimized.

Copy link

@alexdresko alexdresko commented Aug 6, 2019

I get the main gist of this issue, but losing UseWebpackDevMiddleware seems unfortunate. It works great for frameworks that don't have a CLI.

@atrauzzi

This comment has been minimized.

Copy link

@atrauzzi atrauzzi commented Aug 6, 2019

I'm not sure I understand how NodeServices is related to this? What if people want to run JS code from C# for their own purposes?

@NotMyself

This comment has been minimized.

Copy link

@NotMyself NotMyself commented Aug 6, 2019

@alexdresko I agree with you. UseWebpackDevMiddleware is a nice compromise to supporting multiple frameworks. I have been using it for around a year to do Vue.js development, example. It works quite nicely.

@danroth27

This comment has been minimized.

Copy link
Member Author

@danroth27 danroth27 commented Aug 6, 2019

Is UseWebpackDevMiddleware going away with this change? Or UseSpaStaticFiles?

@NotMyself The webpack middleware is part of Microsoft.AspNetCore.SpaServices and will be obsoleted as part of this change. The support for SPA static files is part of Microsoft.AspNetCore.SpaServices.Extensions and will continue to be supported.

@danroth27

This comment has been minimized.

Copy link
Member Author

@danroth27 danroth27 commented Aug 6, 2019

@flcdrg @atrauzzi @ericgreenmix Could you please share with us some details on how you are using NodeServices today? Why do you need to execute JavaScript on the server at runtime? If there is significant interest in this functionality it might be interesting to spin NodeServices off as a community driven project. Is that something any of you would be interested in taking on?

@manigandham

This comment has been minimized.

Copy link

@manigandham manigandham commented Aug 6, 2019

@danroth27

We use NodeServices to run some NPM packages that don't have equivalent .NET libraries and aren't worth a rewrite. This is one of the benefits as mentioned by the team before.

We also have a functions-as-a-service platform that we're building for customers to write their own custom logic in our app using Javascript. There are alternatives like Edge.js (which is not .net core compatible) but NodeServices makes this easy.

There's a lot of value in it and if it's not going to be maintained then we would definitely like to see it as a separate community project.

@jarroda

This comment has been minimized.

Copy link

@jarroda jarroda commented Aug 6, 2019

@danroth27 For the same reason that people do interop generally. In our case, we're using a PDF generation library to do reporting, because there is no equivalent available in netcore for linux platforms. As @manigandham points out, that was a general feature of the library.

@ericgreenmix

This comment has been minimized.

Copy link
Contributor

@ericgreenmix ericgreenmix commented Aug 6, 2019

@danroth27 As others have said, we use it to leverage various NPM packages that don't have equivalents in .Net.

As the repositories readme states:

This provides a fast and robust way for .NET code to run JavaScript on the server inside a Node.js environment. You can use this to consume arbitrary functionality from NPM packages at runtime in your ASP.NET Core app.

What led to the decision of deciding to obsolete the NodeServices without an equivalent replacement? It seems like an oversight to me.

@danroth27

This comment has been minimized.

Copy link
Member Author

@danroth27 danroth27 commented Aug 6, 2019

What led to the decision of deciding to obsolete the NodeServices without an equivalent replacement?

@ericgreenmix Our primary scenario for building NodeServices was to enable integration between SPA frameworks and ASP.NET Core for things like like server-side prerendering and HMR. Since we now integrate with the CLIs for Angular and React directly this functionality is no longer needed for these specific scenarios. Providing NodeServices as a generic way to into JS from .NET Core is not something we want to maintain long term.

@danroth27

This comment has been minimized.

Copy link
Member Author

@danroth27 danroth27 commented Aug 6, 2019

if it's not going to be maintained then we would definitely like to see it as a separate community project.

@manigandham Makes sense. We certainly would encourage folks that are interested in continuing to maintain this functionality as a community based project to do so. If such a community project were to spin up it is more than welcome to use the existing NodeServices code as a starting point with the appropriate changes to the namespaces and package names. We'd be happy to point folks that are interested in this functionality to whatever the community comes up with.

@danroth27

This comment has been minimized.

Copy link
Member Author

@danroth27 danroth27 commented Aug 6, 2019

UseWebpackDevMiddleware is a nice compromise to supporting multiple frameworks. I have been using it for around a year to do Vue.js development, example. It works quite nicely.

@NotMyself We'd like to enable the .NET + Vue community to ship a Vue template that integrates with the Vue CLI similar to what we do for Angular and React. I believe we still have some functionality to make public to make that reasonable to do, but I think that's something we'd like to address in the .NET 5 time frame.

@bugproof

This comment has been minimized.

Copy link

@bugproof bugproof commented Nov 29, 2019

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

@rjgotten

This comment has been minimized.

Copy link

@rjgotten rjgotten commented Nov 29, 2019

@bugproof
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

That's exactly what NodeServices and everything built on it does. Its Node.js instances are plain old Node.js instances running as a normal separate processes and communicating with their parents over a HTTP connection, allowing for basic request->response RPC.

@estebangamez

This comment has been minimized.

Copy link

@estebangamez estebangamez commented Dec 6, 2019

Any reason why there's no official vue project template? Typescript flavor only maybe?

@estebangamez

This comment has been minimized.

Copy link

@estebangamez estebangamez commented Dec 6, 2019

You want to stop server side rendering for SPA templates. The only reason i see is you want to promote Blazor. But don't do this, community need these packages.

Yeah I agree the moment you see promoting their agendas and removing support for the community

@estebangamez

This comment has been minimized.

Copy link

@estebangamez estebangamez commented Dec 6, 2019

wow version 1.0 version 2.0 ... version 3.0 all these improvements sound amazing but there is always a caveat which is kind of sad , I understand software maintenance is not free but makes lose some trust on .net core.Perhaps next year they will come up with a solution/approach ?

@rjgotten

This comment has been minimized.

Copy link

@rjgotten rjgotten commented Dec 8, 2019

software maintenance is not free

The maintenance cost for the Node.js side of things - which is specifically what MS engineers cited as an issue - is a problem that either doesn't exist, or was created due to Microsoft's own ineptitude and failure to act timely.

I've taken a look before. Most of the TypeScript that handles the Node.js interop was not cleaned up; restructured or even touched in literally years.

For the basic NodeServices InvokeAsync that's fine.
It's a very basic thing for which maintenance is basically nil. Any changes required there would either be the result of a discovered bug or a big, backwards-incompatible breaking change in core Node.js modules. Which really never happens on short notice. (Ironically, that type of breakage probably happens far less for Node.js than it does when moving from one release of .NET Core to the next.)

The UseWebpackDevMiddleware has some inherent maintenance cost, but is problematic mostly because it was not kept up to date well at all.
It was written for Webpack 2; was not rewritten to capitalize on improvements from Webpack 3 and 4; and generally is just a big freaking mess put together by people that should have known better, but apparantly didn't spend the effort to learn how to do things properly. And stuff just continued to get stapled on every half year or so, until it too ceased to receive any care or updates.

@GGAlanSmithee GGAlanSmithee mentioned this issue Dec 9, 2019
0 of 2 tasks complete
@CrustyJew

This comment has been minimized.

Copy link

@CrustyJew CrustyJew commented Dec 10, 2019

Am I going crazy here or is the only way to use NodeScriptRunner to build an extension in to the Microsoft.AspNetCore.SpaServices.Extensions package since it is an internal class?

If that was public, we could create a package that adds an extension method for Vue etc without having to build it in to the core Microsoft repository.

Why is this class internal? Can it be made public so we can at least use it to build the tools the Microsoft no longer wants to support? How exactly are we supposed to build a Vue template independently, or is the goal to force it inside this repo?

@rjgotten

This comment has been minimized.

Copy link

@rjgotten rjgotten commented Dec 11, 2019

How exactly are we supposed to build a Vue template independently, or is the goal to force it inside this repo?

The tin-foil hat argument would be that these changes are business-oriented more than anything else; i.e. to push Blazor as the go-to solution. And sadly, introducing roadblocks that stymie alternative endeavors to integrate with SPA frameworks other than Blazor seems to fit right in with that.

@bugproof

This comment has been minimized.

Copy link

@bugproof bugproof commented Dec 11, 2019

@rjgotten Nothing is stopping you from using dedicated SSR solutions for js framework of your choice. Take Jet.com as an example, they're using dotnet (F#) as the backend but they use next.js for SSR, so your backend doesn't really care what your frontend is. I think it keeps the code clean and this obsoleting issue is not a problem for people who chose this route.

Blazor is nice because you can share your code and models easily but it's not released yet (client-side one which I think is superior to server-side blazor)

@alekkowalczyk

This comment has been minimized.

Copy link

@alekkowalczyk alekkowalczyk commented Dec 17, 2019

Does that mean, that if I want server-side rendering in an ASP.NET Core+React project, I need now to split that project into two, with a new Node.JS project holding all the client JS codes and doing the SSR, and the remaining ASP.NET Core project being only responsible for the WebAPI stuff?

@cjblomqvist

This comment has been minimized.

Copy link

@cjblomqvist cjblomqvist commented Dec 17, 2019

Or live with it being deprecated, or move to the alternative discussed above.

@dcb99

This comment has been minimized.

Copy link

@dcb99 dcb99 commented Dec 23, 2019

Any reason why there's no official vue project template?

@bugproof Maintaining templates isn't effortless. This has been discussed in issue: aspnet/JavaScriptServices/issues/412.

I'm not sure that it makes sense to reference a 3-year old discussion. Vue is currently the most popular JS framework and plenty of people in the .net world like using it. Ditching HMR and requiring extra steps for local development is a pain and definitely seems like a regression. Isn't .net core supposed to be making our lives easier?

@Daniel15

This comment has been minimized.

Copy link

@Daniel15 Daniel15 commented Dec 23, 2019

Vue is currently the most popular JS framework

@dcb99 I'm pretty sure that's not true... React is still more popular by far. See the State of JS survey results for example: https://2019.stateofjs.com/front-end-frameworks/

@dcb99

This comment has been minimized.

Copy link

@dcb99 dcb99 commented Dec 23, 2019

@Daniel15

This comment has been minimized.

Copy link

@Daniel15 Daniel15 commented Dec 23, 2019

Stars don't equate to actual usage... Stars aren't a very useful measurement. React has far more downloads on npm (although this also isn't a good measurement, as improperly configured build systems that download packages off the internet for every single build contribute a lot to these numbers) and is ranked higher in various developer surveys.

@dcb99

This comment has been minimized.

Copy link

@dcb99 dcb99 commented Dec 23, 2019

@drdamour

This comment has been minimized.

Copy link

@drdamour drdamour commented Dec 23, 2019

Vue is currently the most popular JS framework

@dcb99 I'm pretty sure that's not true... React is still more popular by far. See the State of JS survey results for example: https://2019.stateofjs.com/front-end-frameworks/

Pretty funny your own link shows vue has 100% awareness, higher interest than anything else, and only trails react in satisfaction by 2% points. Kinda made the point for em...vue is legit popular and from that report is ahead of ng by a bit.

@grbd

This comment has been minimized.

Copy link

@grbd grbd commented Jan 11, 2020

For the UseWebpackDevMiddleware issue I suspect what we need is an implementation similar to this
https://github.com/dotnet/aspnetcore/tree/master/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer
within Microsoft.AspNetCore.SpaServices.Extensions

but instead written for the webpack development server
similar to what's being done here but automated in code instead of being done manually
https://blogs.taiga.nl/martijn/2019/10/11/goodbye-spaservices-it-was-fun-while-it-lasted/

This might allow for existing vue / anything webpack based templates
(which isn't just react or angular) to work with hot module reloading

A bit disappointing that they obsoleted the existing working system, without bothering to write a proper replacement

@chamikasandamal

This comment has been minimized.

Copy link

@chamikasandamal chamikasandamal commented Jan 12, 2020

@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:

  • INodeJSService

    • InvokeFromFileAsync<T>
    • InvokeFromStringAsync<T>
    • InvokeFromStreamAsync<T>
    • TryInvokeFromCacheAsync<T>

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

  • INodeService

    • InvokeAsync<T>
    • InvokeExportAsync<T>

We could add those members to INodeJSService:

  • INodeJSService

    • InvokeAsync<T>
    • InvokeExportAsync<T>
    • InvokeFromFileAsync<T>
    • InvokeFromStringAsync<T>
    • InvokeFromStreamAsync<T>
    • TryInvokeFromCacheAsync<T>

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 : do you have any working samples for prerendering using this?

@JeremyTCD

This comment has been minimized.

Copy link

@JeremyTCD JeremyTCD commented Jan 13, 2020

Hi @chamikasandamal I'm the author of Jering.Javascript.NodeJS. @DaniilSokolyuk's NodeReact.NET uses Jering.Javscript.NodeJS to render React components.

@Daniel15

This comment has been minimized.

Copy link

@Daniel15 Daniel15 commented Jan 13, 2020

@JeremyTCD If anyone is interested in merging that NodeReact.NET project into ReactJS.NET, I'm happy to review pull requests :)

@JeremyTCD

This comment has been minimized.

Copy link

@JeremyTCD JeremyTCD commented Jan 13, 2020

Hey @Daniel15 I think @DaniilSokolyuk is your best bet! I think React is awesome but I'm not a React user myself.

@schmitch

This comment has been minimized.

Copy link

@schmitch schmitch commented Jan 16, 2020

btw. there is no need for anything besides SpaServices.Extensions. Microsoft did a really really lazy job here.

Basically one can use UseReactDevelopmentServer with a webpack devserver.

it's basically as simple as configuring a devserver like that:
dotnet:

                app.Map("/dist", innerApp =>
                {
                    innerApp.UseSpa(spa =>
                    {
                        spa.Options.SourcePath = ".";
                        spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
                    });
                });

webpack

// microsoft want's this line... which is lazy...
// https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/SpaServices.Extensions/src/ReactDevelopmentServer/ReactDevelopmentServerMiddleware.cs#L91
console.log('Starting the development server...\n');
const port = parseInt(process.env.PORT, 10) || 8083;
module.exports = {
            devServer: {
                compress: true,
                port: port,
                contentBase: basePath,
                publicPath: '/'
            },
           .... // your webpack config here
        }

and now you can basically use your css/javascript like you did before, you just need the right path's.
I'm not sure why they called it "react-dev-server" because react dev server is basically webpack. also they could just give us webpack dev server with examples and everybody would be happy.

@johnrom

This comment has been minimized.

Copy link

@johnrom johnrom commented Jan 16, 2020

@schmitch yes, that is SpaServices.Extensions which is not being deprecated. What we're losing here is the core SpaServices / NodeServices which manage IPC with node for server side rendering and other direct node communication.

@grbd

This comment has been minimized.

Copy link

@grbd grbd commented Jan 16, 2020

Starting the development server...

that's actually a good idea adding in the

console.log('Starting the development server...\n');

I started writing my own webpack implementation which was a copy / paste of the react one, but that's a much simpler approach. It would probably work for the vue one as well.
There is however a nasty bug which seems to affect .net core 3.0 and above where the task doesn't quit when VStudio stops debugging or is closed, so you can end up with lots of webpack / react dev servers sitting around in memory until it's manually end tasked which is what I referenced above.

This page suggests doing things a different way which involves sticking the webpack / vue / react dev server in front rather than behind

https://www.dotnetcurry.com/aspnet-core/1500/aspnet-core-vuejs-template

@johnrom

This comment has been minimized.

Copy link

@johnrom johnrom commented Jan 16, 2020

@grbd sticking the webpack server in front requires many http requests between SSR and server for complex projects instead of a single request with pre-populated data -- it's a trade-off. The interesting thing is that all of these are really cheats, because in the real world it'll be a best practice to have two independent projects with different architectures for scalability. In VSCode, I now run something like Razzle (React) w/ a composite launch task that starts both .net core and webpack dev servers which can be started / stopped independently. At scale in production, one would have a separate Node server, and .Net would POST that server with pre-populated data to get a result. What SpaServices and NodeServices supported, though, was for smaller projects with less budget to spin up a simulated version of this environment to get the best of both worlds within a reasonable budget. The same can be accomplished with the community project mentioned above, but I haven't migrated just yet.

Overall, I think I've gotten over the fact it's being obsoleted by Microsoft in support of a community project because of the fact that it is itself somewhat of an anti-pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.