adonisjs / rfcs

💬 Sharing big changes with community to add them to the AdonisJs eco-system
52 stars 6 forks source link

Communicate AdonisJs version more efficiently #12

Closed RomainLanz closed 4 years ago

RomainLanz commented 5 years ago

Hi everyone! :wave:

Since the beginning, Adonis follows a modular approach with the Service Provider concept. When you look at your package.json file in a default boilerplate you will see many different packages added per default.

The issue with this approach is that people never knew which version of Adonis they are using because there’s none Adonis package. Adonis is many different packages that work together and not one big package.

Currently, you could be using Adonis 4.1 but having @adonisjs/lucid at version 6!

This is very confusing for newcomers and even people that are working daily with Adonis.

This is why I want to propose a Rolling Release system for Adonis!

What’s a Rolling Release System?

A Rolling Release is the concept of frequently delivering updates to an application instead of having a large major version. (If you are a Linux guy you can take as example Ubuntu which uses standard release and Arch Linux that follows the rolling release concept)

What that means for Adonis?

Adonis is already following this principle for its modules. Each module is individual and follows semver. This is why you are currently using @adonisjs/lucid at version 6 while Adonis is at version 4.1.

If this RFC is accepted, Adonis will have no version of itself. Only Modules will have their versions.

What changes for the final developer?

  1. It would be easier to update the application since small breaking change will come each week/month and not all at once.
  2. No need to wait X months for new features, you can always be at the edge of Adonis very easily.
  3. No confusion about what version you are using. You will use Adonis with version X of module Y.

How the doc will be?

Each module will have their own Update Guide & Changelog. In the documentation, each function will have a hint with the version when it has been added. So you can quickly know if the function X is available in the release you are using of the module Y.

If we remove a function from a module (after deprecating it for months), we will remove the documentation of it, and the Update Guide will help you understand what to do to replace it.

assertchris commented 5 years ago

I don't have strong feelings on monolith vs. the current structure. What I would prefer to avoid is a situation where it is impossible to know what "version" of the "framework" a tutorial or screencast or news article is about.

Sorry to reference our favourite PHP framework (again!) but it's unmistakable which set of "components" a news article entitled "What's new in Laravel 5.7" is for.

"Is a tutorial, published 2 years ago, still ok? Let me find a list of package versions in it to check. No such list? Oh well, guess I can't depend on what's said in the tutorial..."

assertchris commented 5 years ago

An Adonis "version" doesn't need to be anything more than a number to represent that a collection of differently versioned components actually work when used together. Perhaps it just requires a page on the site to say; "Version X of Adonis certifies that these versions of components function well together. Upgrade individual components at your own risk".

PazzaVlad commented 5 years ago

I personally think that merging core packages (like described here https://github.com/adonisjs/rfcs/issues/2) will be more useful. Let me explain why.

PazzaVlad commented 5 years ago

Agree with @assertchris

EremenkoAndrey commented 5 years ago

Agree with @assertchris Me too

bitkidd commented 5 years ago

Not sure about the benefits of this for three reasons:

  1. Too many packages to consider
  2. Too hard to follow the changelogs
  3. Too unopiniated

The monolyth approach seems much more stable, kinda there is a set of packages that work together we'll, and this combination is called Adonis 4.5.1, for example. It feels natural.

thetutlage commented 5 years ago

As I shared in the other thread about merging some packages to the core. Yes, we will merge them together and form a single package called @adonisjs/framework.

Adding anything apart from those packages is making the framework too bloated. For example: Laravel has to create Lumen, in order to serve people who doesn't need everything and maintaining a parallel framework isn't that simple and has it's own drawbacks.

No to monoliths

No matter what you choose, you get downsides for free. By keeping certain packages separate, we make the framework more approachable for people, who are not building full blown server rendered apps.

I myself have projects running with

For all these use-cases, asking people to run a full blown framework is not fair.


Now, as we are clear that Monoliths is something I doesn't want (which maybe debatable, but there is no point debating), let's move forward

I am interested in finding the best way to release multiple packages, but still keep it clear for the users about the internal dependencies.

In nutshell we will have following packages (the list may grow in future).

I am happy using @adonisjs/framework version as the main version for everything (docs, creating content and so on) and all other packages can have their own release cycle.

This concept is not new and many other frameworks are already doing it.

VueJs does this with their own packages, like vue-router, veux and so on.

screen shot 2018-10-08 at 5 35 21 pm

Same is done by Ember with Ember data

screen shot 2018-10-08 at 5 19 49 pm

For the community, by the community

I am not rigid on the versioning scheme (just no to complete monoliths). I want it to be easier for everyone to understand, how versioning works and how to upgrade their apps easily.

assertchris commented 5 years ago

As I said before (and to try and recover a clear position in spite of the +1s): I don't have strong opinions of monolith vs. how you're planning to structure independent repos. What I don't want to see is a situation where it is unclear which versions of components are referred to in a given situation because there is no compatibility version number.

That compatibility number is what you get for free when structured as a monolith. You've stated reasons why you don't wan a monolith and I understand them. That doesn't mean we can't have Adonis version X which makes it clear which versions of components are working together.

When you place the burden of figuring out which components are (or should be) used together, you make it much harder to know if teaching materials are outdated or even if the application is still going to work post npm up.

Hiding that info in the docs is not much better than omitting it altogether, because now someone has to study the docs in their entirety to get a handle on the constraints of each package. You're making the developer do dependency resolution instead of NPM. Folks well acquainted with the ecosystem might not struggle much with this task, but the average (or new) developer definitely will.

mourad-ghafiri commented 5 years ago

Angular stragtegy of version alignement had a great success... skipping version 3 to bring all modules to version 4...

you can do the same and bring everything to Adonis 6 or so...

Gooe luck :)

thetutlage commented 5 years ago

My comment clearly says that I am using @adonisjs/framework version as the main version of the framework. So my approach is different from what Romain lanz shared.

To make sure I am not making it confusing. Here’s what I mean

assertchris commented 5 years ago

and you have to read docs to know that

😞

Do you think it would be possible to put a dependencies version constraint on the first party packages, so that NPM/Yarn could "read the docs" for the developer?

RomainLanz commented 5 years ago

If you believe that you can take a framework and work with it while never reading its doc you are wrong.

Also, peerDependency will be used to warn the user.

assertchris commented 5 years ago

That's a misrepresentation of what I said. From what @thetutlage has said, it doesn't even sound like the docs he is referring to are the framework's docs; so there's that too.

I'm not saying it should never be in the docs, or that nobody should have to use the docs. I'm saying NPM and Yarn provide a mechanism for this to happen without the developer needing to read the docs about version constraints. Given that, it seems like an unnecessary stumbling block.

assertchris commented 5 years ago

Also, peerDependency will be used to warn the user.

From what I've read about peerDependencies, the developer will need to resolve the version conflicts themselves. If the first-party packages must be used with specific versions of AdonisJS, then it seems strange to allow them to be installed with other (non-compatible) versions: even if the developer is warned otherwise.

Am I understanding the mechanics of peerDependencies correctly, or will it not be possible to install Lucid with...say...an incompatible version of AdonisJS..?

thetutlage commented 5 years ago

@assertchris how do u stop installation of incompatible packages at first place using npm or yarn? I’ll be the happiest person on planet, if npm can help me do that

assertchris commented 5 years ago

Unless I'm missing something obvious: Lucid requires framework 6, so it specifies "@adonis/framework": "^6.0.0" in dependencies. When someone tries to install Lucid, it will make sure version 6 is installed or NPM/Yarn won't install Lucid to begin with.

thetutlage commented 5 years ago

@assertchris Nope.

Let's say lucid relies on "@adonis/framework": "^6.0.0" Your app is running "@adonis/framework": "^5.0.0"

Then npm will install a different 2 copies of @adonis/framework, and Lucid will use a different version then your app. Which is more dangerous.

As @RomainLanz said peerDependencies are the way to tell users about the mis-match, since npm does warn you about it.

assertchris commented 5 years ago

Lucid will use the version in it's node_modules folder, which would still be version 6.

RomainLanz commented 5 years ago

Unless I'm missing something obvious

You are.

Using peerDependencies let the final developer install the correct package. If your application is using "@adonis/framework": "^5.0.0", and the new version of Lucid use "@adonis/framework": ">6.*" in its peer dependencies, NPM will warn you that you cannot use this version of Lucid because your version of @adonis/framework doesn't match the required version.

assertchris commented 5 years ago

@RomainLanz

You are.

And, then you repeat exactly what I said here:

...the developer will need to resolve the version conflicts themselves.

peerDependencies warn but don't enforce. dependencies enforce (for that specific node_modules folder). That appears to be what the docs are saying. Do you still think I'm missing something in that definition?


I know it's difficult to read tone on the internet, and I am assuming the best here. Please try to remember that I'm not arguing against you – I'm arguing for making things easier for the developer.

thetutlage commented 5 years ago

@assertchris

Lucid will use the version in it's node_modules folder, which would still be version 6.

But the framework version has to be shared between your app and Lucid. Ideally framework is not right dependency here. Let's talk about IoC container instead.

If lucid is running a different copy of IoC container, and your app is running a different copy, then bindings in the IoC container won't be shared.

This is what peer dependencies is for. If npm Warns then it is npm who decided to warn. All packages, which want to use main app dependencies works on top of peerDependencies only. It is true for babel, eslint or any other.

https://github.com/babel/eslint-plugin-babel/blob/master/package.json#L30 https://github.com/vuejs/vuex-router-sync/blob/master/package.json#L41

So the idea of peerDependencies is not debatable and also dependencies is not the right way to achieve what we want.

assertchris commented 5 years ago

I see what you're saying. Thanks for taking the time to explain. Just to be clear – the global mutable state, shared between framework and the first-party components, is forcing peerDependencies over dependencies then?

In that case, I now have strong opinions over monolith vs. the proposed structure. As you've already explained you won't budge over that issue, I guess there's nothing more for me to talk about here.

thetutlage commented 5 years ago

Finally going with the approach shared in https://github.com/adonisjs/rfcs/issues/12#issuecomment-427882012

RomainLanz commented 4 years ago

Closing.

https://preview.adonisjs.com/release-process