TL;DR: If you develop a JavaScript library component that depends on @aspnet/signalr
, we'd like to hear from you!
One open question that we'd like some support from the community on is how to manage the name transition. Here, we'd love feedback from app developers and anyone developing other NPM components that depend upon @aspnet/signalr
.
My biggest concern is if a library component references @aspnet/signalr
at version >=1.0.0
. They are saying they work with versions 1.0 and higher, but the problem is that version 3.0 is not part of that set (because it's a different package name).
We have a few options
@aspnet/signalr
.@aspnet/signalr
don't know that we changed@aspnet/signalr
(probably version 3.0
) and immediately deprecate it on NPM.@aspnet/signalr
either have to update, or can't get the new stuff@aspnet/signalr
as a "shim package". This would be a package that has a direct dependency on the matching version of @microsoft/signalr
and re-exports all the types. So it's content would be something like the snippets below@microsoft/signalr
) and references a library using @aspnet/signalr
version 1.x
(BEFORE the shimming), then they may end up with two copies of the library. The 1.x
version of @aspnet/signalr
and the 3.x
version of @microsoft/signalr
. Thanks to JavaScript this will probably still work, types can be exchanged just fine.I think if we did option 3, we'd also mark each release of these shims as deprecated so that NPM users get the warning. That means that if an app did use @microsoft/signalr
and a library it depends on used @aspnet/signalr
you would get a warning indicating you were in a slightly odd state. If you manually installed the shim package @aspnet/signalr
it would fix the odd state since now the library would be using the shim and there'd only be one copy of @microsoft/signalr
@aspnet/signalr
package.json
{
"name": "@aspnet/signalr",
"main": "index.js",
"dependencies": {
"@microsoft/signalr": "[exact same version]"
}
}
@aspnet/signalr
index.ts
export * from "@microsoft/signalr"
Another option I just thought of:
@microsoft/signalr
shims for the existing @aspnet/signalr
packages which just re-export @aspnet/signalr
types, like the other proposed shim above.Thoughts @davidfowl @bradygaster @BrennanConroy @mikaelm12 @halter73 ?
I'm leaning hard to option 4 here. It provides a clear migration path for everyone, doesn't require us to keep maintaining shims (since we just ship one-time @microsoft/signalr
shims for existing @aspnet/signalr
versions) and type identity works fine because JavaScript. We can deprecate all versions of @aspnet/signalr
(assuming that doesn't mess with the shimming) to tell everybody to just flip over to @microsoft/signalr
To be clear, these new packages would be one for each currently-released version of @aspnet/signalr
, and would look like this:
@microsoft/signalr
package.json
{
"name": "@microsoft/signalr",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@aspnet/signalr": "=1.0.0"
}
}
@microsoft/signalr
index.ts
export * from "@aspnet/signalr"
So far I'm with @anurse on option 4 seeming to be the path of least resistance and maintenance.
And if we patch the npm package will we only update the new @microsoft/signalr
package or do both?
And if we patch the npm package will we only update the new @microsoft/signalr package or do both
Yes, this is also my concern. I feel like servicing both will become a thorn in our side.
[Edited] Having @aspnet/signalr
have a direct dependency on @microsoft/signalr
feels dishonest for lack of a better word. I'm not sure if allowing two ways to get the same version of client in general is the best approach. I'm personally leaning towards just not continuing to ship the @aspnet/signalr
package. It will be unfortunate that we'll end up in the same situtation as we have with the java client have both the aspnet and microsoft branded packages published and potentially confusing customers.
To clarify, as you mentioned @signalr/signalr
so I just want to make sure I got your point, reworded below:
Having
@microsoft/signalr
have a direct dependency on@aspnet/signalr
feels dishonest for lack of a better word. I'm not sure if allowing two ways to get the same version of client in general is the best approach. I'm personally leaning towards just not continuing to ship the@aspnet/signalr
package. It will be unfortunate that we'll end up in the same situtation as we have with the java client have both the aspnet and microsoft branded packages published and potentially confusing customers.
I'm inclined to agree with @mikaelm12 philosophically on this, as it does seem weird (like it did years ago when Jeff described a similar pattern in NuGet) to actually be pulling the @aspnet/signalr
package when you asked for the @microsoft/aspnet
package. However, I think it is the path of least resistance for folks who have taken a dependency.
I'm also thinking of the community that requested we do this; the implication is folks didn't want to use it because of the implication that "ASP.NET is a requirement for SignalR." If we do it this way, the
@microsoft
one will actually be the @aspnet
one. Curious what those who proposed we do this would say about it - if it doesn't feel dishonest or spicy with them, I'm okay with it provided we agree it's the path of least resistance for customers and ourselves.
Didn't mean @signlar/signalr
! My b. Editing it now to read @aspnet/signalr
Hey hi hello π
I have some thoughts/opinions that I wanted to share:
I would not recommend doing any kind of mirroring of APIs. It creates a lot more work for a negligible amount of end-user benefit. The amount of work needed to set this up, maintain it, and β most importantly β fix it if anything goes wrong is a much higher cost than any possible end-user benefit that I am aware of. If you want to get into technical reasons, this is not a good path because it effectively gets around npm
, yarn
, pnpm
and any other package manager's deduping of redundant modules which will end up increasing deployment/bundle sizes for end-users.
Having
@microsoft/signalr
have a direct dependency on@aspnet/signalr
feels dishonest for lack of a better word.
I 100% agree. Being totally honest: if I'd seen this before I worked at Microsoft, my assumption would be that whoever did this was not a part of the JavaScript ecosystem and was instead just someone from .NET trying to make the JS folks happy while not really caring about them.
Regardless of the positive intent, it strays from how the JavaScript ecosystem works and comes off as uninformed/unaware β which is definitely not my experience with the SignalR team(s) so far now that I'm at Microsoft.
I'm also thinking of the community that requested we do this; the implication is folks didn't want to use it because of the implication that "ASP.NET is a requirement for SignalR."
Being totally unaware of SignalR before working at Microsoft, this wasn't quite my perception. The perception I had when learning about @aspnet/signalr
was that SignalR was _only_ for ASP.NET β meaning I couldn't use it as a Node.js developer. But, I suppose that could technically also be perceived as ASP.NET being a req for SignalR usage.
As a Node.js ecosystem member, I'd like to make a suggestion β definitely weigh the pros/cons but IMO it makes the most sense _to me_:
Do option 2. Walking through _why_:
Additionally, I'd like to share some reasons why I'd be _extremely hesitant_ to suggest Option 4:
@aspnet/signalr
. If there is _one single_ inconsistency in any/all of the re-publishes, you have 72 hours from publish to either delete it or re-publish because of npm's unpublish policy. This is something I would strongly recommend against.@aspnet/signalr
modules will continue to work perpetually β they're not going anywhere, since they're immutable. As such, there's no real need for something like a migration path _for those older versions with the new namesapce_. If you're using those versions, you point to @aspnet/signalr
. If you're using newer versions, you point to @microsoft/signalr
. The only kind of migration that _should_ be happening is whatever semver major changes are introduced in the newer version β adding an additional change to a LOC that would have _already_ changed should be theoretically uncontroversial.I'm actually thinking this is the win-win scenario. We have to ship these weird back-versioned shims but they're stable and never need to be updated.
@aspnet/signalr
if those are the versions someone is already depending on β changing to @microsoft/signalr
for the versions that are currently published actually _increases_ the amount of work they'd need to do, since they _already_ have those versions pointed to the existing working module.Since I have a lot of friends who maintain a non-trivial amount of packages on npm, I decided to ask about this in a general sense on Twitter. The responses so far have been super interesting:
joy
=> @hapi/joy
that uses a good deprecation message and points to the new one: https://www.npmjs.com/package/joi (thanks Dominik Kundel!)Thanks for your insight on the issue @bnb! Your perspective is really appreciated!
Happy to help, @mikaelm12! β€οΈ
Hey,
I'd like to chime in and provide some feedbackβas a member of the JavaScript community and a maintainer/author of some Node packages.
@bnb had already provided a much more detailed response.
So, definitely go for option 1: publish the new package and deprecate the old one, making sure to provide the right communication about this change and how they can get the new package. This, of course, would be considered as a breaking change, so developers would anyway have to check the new API deprecations and update their existing code. In the process, you would have an extra step which updating their package.json
with the new scope.
Cheers.
This is great perspective! I'm mostly happy to defer to the JS community experts here, but I do want to make sure I have clarity on things here.
- No new version needs to be shipped β deprecation can be done directly without shipping a new version.
Unfortunately this isn't true since _none of our existing published versions are considered deprecated_. They remain fully supported and will be patched in accordance with the .NET Core Support Policy. I think that marking them deprecated would be misleading. Of the current versions, only the 3.0
preview releases would be actually deprecated. The 1.0.x
releases (aligned with .NET Core 2.1) are supported until at least August 2021 and the 1.1.x
releases (aligned with .NET Core 2.2) are supported until December of this year/
This is why option 2 requires the publishing of a new version to indicate to those interested in updating how to actually do so. We could in theory wait for the 1.1.x
releases to go end-of-life and deprecate those then.
- The
@aspnet/signalr
modules will continue to work perpetually β they're not going anywhere, since they're immutable. As such, there's no real need for something like a migration path _for those older versions with the new namesapce_.
It's not entirely true that there's no real need to provide this migration path. Consider a _library_ that has a dependency on @aspnet/signalr
. In general, we strive to preserve compatibility across major version boundaries unless necessary, and it's my understanding that we haven't made any major breaking changes in 3.0 to the client API. A library or app written against @aspnet/signalr 1.0
should be expected to work against @microsoft/signalr 3.0
. Unfortunately there's no way to express that (to my understanding at least) since this is a completely new package identity.
I'm not clear on how simply publishing a new package doesn't end up bifurcating the ecosystem, though maybe the ecosystem (libraries depending upon the SignalR client) is not large enough to be a concern here.
if I'd seen this before I worked at Microsoft, my assumption would be that whoever did this was not a part of the JavaScript ecosystem and was instead just someone from .NET trying to make the JS folks happy while not really caring about them.
Perhaps this is just naivetΓ© regarding how the JS community organizes. That's why we want to get this information, to find out what the community would find most useful.
Certainly, option 2 doesn't exclude us from taking actions listed in the other options though. I'm quite happy to move forward with that plan and if we hear that this is causing issues in the ecosystem, we can move on.
This is why option 2 requires the publishing of a new version to indicate to those interested in updating how to actually do so.
If this is the path that ends up being chosen, my suggestion is to publish a patch version that includes a new message in the README.md file β effectively, for display only on npmjs.com.
My only concern with this is that you're publishing something that end-users would expect to be code/improvement, but it's actually a misdirection of how to use the real thing. Not a massive deal if it's a few lines in README.md and a patch version, though! π
Unfortunately this isn't true since none of our existing published versions are considered deprecated. They remain fully supported and will be patched in accordance with the .NET Core Support Policy. I think that marking them deprecated would be misleading. Of the current versions, only the 3.0 preview releases would be actually deprecated. The 1.0.x releases (aligned with .NET Core 2.1) are supported until at least August 2021 and the 1.1.x releases (aligned with .NET Core 2.2) are supported until December of this year/
This is totally fine, then - no deprecation needs to occur. Current consumers that are unwilling/unlikely to upgrade (there are always some!) can continue on their happy path. I would highly recommend planning on shipping deprecation at the time where the relevant versions go EOL β€οΈ
I'm not clear on how simply publishing a new package doesn't end up bifurcating the ecosystem, though maybe the ecosystem (libraries depending upon the SignalR client) is not large enough to be a concern here.
It does to some extent, but now is a good time to do it for a few reasons:
Additionally, one of the core tenets of the JavaScript ecosystem is iterating fast. There will definitely be some bifurcation for a short period, but the newer always outgrows the older rather rapidly. 6to5 => Babel is an example of this that had relatively similar reasoning behind it, and was at a much larger scale. I've not heard about 6to5 or seen real-world usage in years. Ironically, they did this again with babel => babel-cli several versions later.
Perhaps this is just naivetΓ© regarding how the JS community organizes. That's why we want to get this information, to find out what the community would find most useful.
β€οΈ
Triage decision: We will do option 1 for now. It doesn't prevent us from doing other things to adjust. @bradygaster will look at the Dependents for @aspnet/signalr
and consider reaching out directly to the frequently-downloaded ones.
Closing since there's no engineering action!
Most helpful comment
Hey hi hello π
I have some thoughts/opinions that I wanted to share:
I would not recommend doing any kind of mirroring of APIs. It creates a lot more work for a negligible amount of end-user benefit. The amount of work needed to set this up, maintain it, and β most importantly β fix it if anything goes wrong is a much higher cost than any possible end-user benefit that I am aware of. If you want to get into technical reasons, this is not a good path because it effectively gets around
npm
,yarn
,pnpm
and any other package manager's deduping of redundant modules which will end up increasing deployment/bundle sizes for end-users.I 100% agree. Being totally honest: if I'd seen this before I worked at Microsoft, my assumption would be that whoever did this was not a part of the JavaScript ecosystem and was instead just someone from .NET trying to make the JS folks happy while not really caring about them.
Regardless of the positive intent, it strays from how the JavaScript ecosystem works and comes off as uninformed/unaware β which is definitely not my experience with the SignalR team(s) so far now that I'm at Microsoft.
Being totally unaware of SignalR before working at Microsoft, this wasn't quite my perception. The perception I had when learning about
@aspnet/signalr
was that SignalR was _only_ for ASP.NET β meaning I couldn't use it as a Node.js developer. But, I suppose that could technically also be perceived as ASP.NET being a req for SignalR usage.As a Node.js ecosystem member, I'd like to make a suggestion β definitely weigh the pros/cons but IMO it makes the most sense _to me_:
Do option 2. Walking through _why_:
Additionally, I'd like to share some reasons why I'd be _extremely hesitant_ to suggest Option 4:
@aspnet/signalr
. If there is _one single_ inconsistency in any/all of the re-publishes, you have 72 hours from publish to either delete it or re-publish because of npm's unpublish policy. This is something I would strongly recommend against.@aspnet/signalr
modules will continue to work perpetually β they're not going anywhere, since they're immutable. As such, there's no real need for something like a migration path _for those older versions with the new namesapce_. If you're using those versions, you point to@aspnet/signalr
. If you're using newer versions, you point to@microsoft/signalr
. The only kind of migration that _should_ be happening is whatever semver major changes are introduced in the newer version β adding an additional change to a LOC that would have _already_ changed should be theoretically uncontroversial.@aspnet/signalr
if those are the versions someone is already depending on β changing to@microsoft/signalr
for the versions that are currently published actually _increases_ the amount of work they'd need to do, since they _already_ have those versions pointed to the existing working module.