recipes icon indicating copy to clipboard operation
recipes copied to clipboard

Symfony webapps and their hard reliance on Stimulus

Open NMe84 opened this issue 2 years ago • 16 comments

This has been bugging me for a while and I never really knew where to bring this issue up. I ran into it again today and decided that instead of just staying quiet I should just decide on a place to bring this up and start a discussion, so here we are.

I'll just get right to the point: I don't understand why, when creating a new webapp project, Symfony is opinionated on which Javascript libraries to use. Nowadays when you create a new webapp, Symfony includes Stimulus and the Stimulus-bridge (which is fine) but then after that the default recipe also creates the setup for Stimulus in Webpack's config and actually includes the folder and file structure for it.

I think this is a fundamentally bad idea. I don't have anything against Stimulus and I understand that the option should be there, but it should definitely not be on by default. If I want to use React, Angular, Vue, Svelte or any other option I first have to remove all the boilerplate that the recipe added and in recent times that's literally what my process looks like whenever I start a new project: I install Symfony, then go back manually and remove anything Stimulus related. Ever single time. It's annoying and unnecessary and I can't for the life of me understand why any of it is enabled by default in a framework that otherwise says it's as unopinionated as it can be. And I can't be the only person who has this issue, the other frameworks I mentioned are by far more popular than Stimulus has ever been and most likely more popular than it ever will be.

Can someone enlighten me and explain what I'm missing? And would you be willing to reconsider this default behaviour?

NMe84 avatar May 25 '22 13:05 NMe84

Thank you for opening this discussion.

To be clear, you are getting all that boilterplate you complain about when you use the --webapp switch for the symfony new command:

symfony new --webapp my-new-app

What exactly is a webapp? Or rather, what is a good skeleton for a webapp? You probably realize that if you ask ten developers this question, you will get eleven answers. At least. That webapp switch is opinionated by design and if we changed what it does, we would just implement someone else's opinion.

If you omit that switch, you get a minimal project to which you can add only what you need. As long as you don't install any Stimulus-related packages, you should not get Stimulus-related boilerplate.

I myself hardly use --webapp because I do have strong opinions on how my app should be laid out and which libraries it should use for what purpose. I don't expect a scaffolding tool like Symfony Flex to meet those opinions, so starting with the minimal app is the best way for me.

What's stopping you from starting with the minimal app like I do?

derrabus avatar May 25 '22 14:05 derrabus

That webapp switch is opinionated by design and if we changed what it does, we would just implement someone else's opinion.

No, the alternative is simply not installing anything that is going to have heavily different opinions. Not having an opinion is not the same as having different opinions. Everything else that is installed with a webapp project is fairly vanilla stuff, everything else it includes is either part of Symfony's own ecosystem (Forms, Mailer, Messenger, etc) or it's a massively popular external project that despite being external is still the most popular solution to a problem that will need solving in every webapp (Doctrine, Twig). Stimulus does not fit that description. It is not a logical default to force on people. I would have understood if you had picked React or Vue, being as popular as they are, but with Stimulus I am willing to bet that the vast majority of all your users are either removing it or are simply not aware it's being included and leave it in there unused.

What's stopping you from starting with the minimal app like I do?

Because that would change the process from having to remove things to get to a reasonable starting point to having to add things to get to a reasonable starting point. Prior to Stimulus being added into the recipes I would say you had a very good starting point. And you still do, all of the default choices other than Stimulus seem reasonable.

NMe84 avatar May 25 '22 14:05 NMe84

No, the alternative is simply not installing anything that is going to have heavily different opinions.

That's basically the minimal app. People have different opinions on ORMs (or databases in general), template engines, mail clients, serializers, … You have accepted our choices here, but not everybody does.

Stimulus does not fit that description. It is not a logical default to force on people.

Okay, first of all, nobody's forcing anything on anyone. Secondly, it is if you want to work with the Symfony UX components which is currently our recommendation for building a frontend for a webapp.

I would have understood if you had picked React or Vue

As an Angular user, I feel locked out. But seriously, I don't see how the exact same argument would not be brought up if we installed Vue.

What's stopping you from starting with the minimal app like I do?

Because that would change the process from having to remove things to get to a reasonable starting point to having to add things to get to a reasonable starting point.

How's that worse? What would you need to start from the minimal app instead?

Prior to Stimulus being added into the recipes I would say you had a very good starting point. And you still do, all of the default choices other than Stimulus seem reasonable.

So you basically need an easy way to install everything but the Stimulus-related packages?

derrabus avatar May 25 '22 15:05 derrabus

That's basically the minimal app. People have different opinions on ORMs (or databases in general), template engines, mail clients, serializers, … You have accepted our choices here, but not everybody does.

Sorry, but no. Doctrine and Twig are indeed opinions/choices I have accepted, but the mailer and serializer as well as the messenger and other components do not have any opinions on which mail server, which serializer or which messaging stack you should use. The components are there but they don't enforce any opinion. Doctrine and Twig are the only packages included in the webapp project that are.

Okay, first of all, nobody's forcing anything on anyone. Secondly, it is if you want to work with the Symfony UX components which is currently our recommendation for building a frontend for a webapp.

Symfony UX is not included in the webapp project. This particular opinionated choice seems to come from the Webpack Encore package, and it does not belong there. I would follow your line of reasoning if it was symfony/ux that included the dependency but that's not relevant in this particular issue.

How's that worse? What would you need to start from the minimal app instead?

I would have to look up or be aware of all the boilerplate stuff every time I start a new project even though 99% of it is stuff that you have a perfect recipe for that somehow includes things it shouldn't have an opinion on. It is not hard, it's just unnecessary extra work, just like removing Stimulus is not hard, just annoying.

So you basically need an easy way to install everything but the Stimulus-related packages?

That would help me, but I firmly believe that from a design perspective Symfony should not be "telling me" to use Stimulus or to set up Stimulus for me except when I ask for it explicitly. I would be making the same argument if Symfony started setting up RabbitMQ because you decide that this is the MQTT service you want to recommend or if Symfony started setting up MongoDB because that's the NoSQL database you recommend.

Webpack and Webpack Encore have everything on board to get started with your project and your frontend frameworks of choice. Symfony should not be making this decision.

NMe84 avatar May 25 '22 15:05 NMe84

I don't really get the part why it's installed with the symfony/webpack-encore-bundle. The sass-loader isn't installed by default either, but stimulus seems to be treated as a special case.

Most defaults symfony suggests are logical, but for some reason it was decided that stimulus would be a logical default for all symfony applications when using the webpack encore bundle. It would be nice to at least understand why symfony would push something like this.

shades684 avatar May 25 '22 15:05 shades684

That's basically the minimal app. People have different opinions on ORMs (or databases in general), template engines, mail clients, serializers, … You have accepted our choices here, but not everybody does.

Sorry, but no. Doctrine and Twig are indeed opinions/choices I have accepted

Choices you have accepted. That's my point. Especially developers who choose not to use an SQL database would want to remove most of the Doctrine stuff.

Symfony UX is not included in the webapp project. This particular opinionated choice seems to come from the Webpack Encore package, and it does not belong there. I would follow your line of reasoning if it was symfony/ux that included the dependency but that's not relevant in this particular issue.

Okay, that's a very good point. Maybe @weaverryan can give us some insights here. The fact that Stimulus is installed with WebpackEncoreBundle is indeed surprising.

How's that worse? What would you need to start from the minimal app instead?

I would have to look up or be aware of all the boilerplate stuff every time I start a new project

No, the boilerplate is installed by Flex if you install the corresponding Composer packages. You can lookup the packages that --webapp installs here: https://packagist.org/packages/symfony/webapp-pack

You could even publish your own pack with only the dependencies you want by default. Start from the minimal app, install your pack afterwards and you should be good to go. If you weren't aware of that, please feel free to submit a PR to the documentation to help others who are in the same situation.

I firmly believe that from a design perspective Symfony should not be "telling me" to use Stimulus

Again, that's not what's happening.

or to set up Stimulus for me except when I ask for it explicitly.

That's probably something worth working on. Let's put the discussion on --webapp aside here. By installing WebpackEncoreBundle, you certainly don't ask for Stimulus and I tend to agree that it should not be installed or set up in that case.


tl:dr: I think it's fine to get a basic Stimulus setup when using --webapp, but not when starting minimal and adding WebpackEncoreBundle.

derrabus avatar May 25 '22 16:05 derrabus

I'll just quote and respond to this one part because I don't think it's productive to discuss about semantics too much. I've basically said how I feel about the other things and whether or not you agree with them it's not going to be productive if I repeat them in other words.

tl:dr: I think it's fine to get a basic Stimulus setup when using --webapp, but not when starting minimal and adding WebpackEncoreBundle.

This is indeed the main problem I see. If we could at least get some clarification about why this coupling exists that would already help, because right now I just don't understand it. And if there isn't a good reason for it I would suggest putting that part of the recipe where it makes more sense. If see no objections to it being in symfony/ux as it actually has a connection with that and installing that is always a conscious choice.

NMe84 avatar May 25 '22 16:05 NMe84

Okay, that's a very good point. Maybe @weaverryan can give us some insights here. The fact that Stimulus is installed with WebpackEncoreBundle is indeed surprising.

This was done for two reasons:

  1. To be opinionated (yes, this is on purpose, but I understand that not everyone will agree) about giving people a nice JavaScript framework to get started.

  2. For the Stimulus setup, we need a few files in assets/: boostrap.js, controllers/hello_controller.js, controllers.json. We also need app.js to be modified to import bootstrap.js. And we also need a few items to be added to package.json. These recipes files need to live somewhere. Putting them with WebpackEncoreBundle was an easy choice. If we don't put them there, then... I think would need some meta/fake package to attach the recipe to - e.g. composer require symfony/stimulus. This wouldn't actually install anything, but would just bring in the recipe. But then the app.js file would still need to be modified (to add one line), which isn't something the recipe system can do.

I understand that the inclusion of Stimulus with the WebpackEncoreBundle recipe isn't perfect. However, the only decisions I see are:

A) Create a fake composer require symfony/stimulus package for the recipe... but it would have the disadvantages noted above. It would also require updating documentation, screencasts, etc. That second point is not a good enough reason to do it, but change has cost, so the change needs to be worth it.

B) Include the Stimulus recipe files with WebpackEncoreBundle as they are done now. This inconveniences people who don't want to use it, as they need to (a) remove a few packages from package.json, (b) delete bootstrap.js and controllers.json and (c) remove 1 line from assets/app.js.

I strongly vote for (B), which is what we have now. But I know that we cannot make everyone happy, and I think that you bring up valid points.

Cheers!

weaverryan avatar May 25 '22 16:05 weaverryan

Actually, let me update with one more thought. IF there were a way to have a symfony/webpack-encore-bundle recipe that contained the "base" stuff (e.g. package.json, assets/app.js) AND then a symfony/ux recipe that correctly added Stimulus + the UX files (including adding the import './bootstrap') line to app.js, then I think I would support this. There actually is no symfony/ux package, but we could make this a pack that included symfony/webpack-encore-bundle.

However, I believe there are some roadblocks in Flex to get this. First, I think (?) that since a pack is added then uninstalled immediately, its recipe may be added then removed immediately. Second, the EncoreBundle recipe would need to run first so that the package.json is added... so that symfony/ux's recipe could update package.json with some new entries. But then... somehow symfony/ux would need to "overwrite" the app.js file with its new version (which just has one extra line of code).

weaverryan avatar May 25 '22 17:05 weaverryan

So what you're saying is that you wanted to make a clearly unpopular opinionated choice (Stimulus has 184k weekly downloads while much popular choices like React, Vue and Angular each have millions) and because you made that choice you had to go for an imperfect solution that installs things people don't want combined with a package it should not be in? Did I summarize that correctly? Because if I did I very strongly don't agree that this choice is a wise one or even a remotely desirable one. I could have understood if we were talking about any of the more popular frameworks I just mentioned but as is Stimulus is a very weird choice to pre-install and pre-configure for people who just want to create a Symfony project from scratch. By far most of your users will have zero experience with it, it makes no sense for this to be the default.

Nor does it make sense for there to be a default at all in the first place, but as you said in your first bullet point you already knew people would disagree on that.

NMe84 avatar May 25 '22 17:05 NMe84

First, I think (?) that since a pack is added then uninstalled immediately, its recipe may be added then removed immediately.

We have meta packages for that purpose (e.g. symfony/psr7-meta). Those are empty like packs, but unlike packs they're not unpacked. They remain in your composer.json and their recipies are installed and can be updated.

Second, the EncoreBundle recipe would need to run first so that the package.json is added... so that symfony/ux's recipe could update package.json with some new entries.

Flex is already capable of optionally updating docker-compose setups IIRC. Could we do something similar with package.json? Like promting the user that the recipe foo/bar likes to add dependencies to package.json, giving them the choice to accept or reject that?

derrabus avatar May 25 '22 17:05 derrabus

@NMe84 I would really appreciate it if we could discuss this matter on a less emotional level.

derrabus avatar May 25 '22 17:05 derrabus

@derrabus Yes, I think the metapackage idea would be the way to go. I think this setup would work:

A) symfony/ux would be a "pack" that would include symfony/webpack-encore-bundle and symfony/ux-meta.

B) symfony/ux-meta would DUPLICATE (<-- not ideal, but manageable) the recipe for webpack-encore-bundle. This is needed so that the package.json file is present... so that this recipe could add the Stimulus & UX stuff. The recipe would also come with a customized app.js and webpack.config.js: each need 1 line to boot up the Stimulus/UX setup.

C) symfony/webpack-encore-bundle's recipe would be simplified to include the Encore stuff, but not Symfony or UX.

For users, the install would be composer require symfony/ux or just composer require ux. We could still include that in the webapp. The minor downside is that a symfony/ux-meta package would remain in the user's composer.json.

@NMe84 So what you're saying is that you wanted to make a clearly unpopular opinionated choice

I think you have brought up a valid point with this. But please keep the conversation respectful.

weaverryan avatar May 25 '22 17:05 weaverryan

I'm not sure how I'm being disrespectful when I point out flaws in an argument. You made the decision to be opinionated on something that I strongly believe Symfony should not be opinionated on at all and after deciding to do that ended up with having to enforce that opinion in a place where it doesn't belong because of technical limitations. The more logical choice would be to then simply not go for the addition, at least in my opinion.

I meant no disrespect and I'm sorry if I came across that way. But I do feel very strongly about some of the choices that were made here and I'll be honest: I'm still entirely unsure about why they were made in the first place.

Having said all that, I'm glad you're thinking about this and are looking into better solutions. I won't pretend that I know enough about the essential details here so I'll let you do your thing without making the process harder by further repeating things I've already said.

NMe84 avatar May 25 '22 23:05 NMe84

I very much support the proposed changes, as I have also faced the surprise of default recipes including the Stimulus boilerplate that I had to strip and delete right away. The purpose of the recipes was always to facilitate the vast-majority scenarios, and as such out-of-the-box choices like Twig and Doctrine are perfectly defendable. Stimulus does not hold the same status inside or outside the Symfony community.

And totally offtopic - I didn't see any disrespect in this entire topic, and was surprised to suddenly see references to 'disrespectful' behavior coming up. Objectively disagreeing with someone's technical choices based on solid objective arguments is not disrespectful and bringing 'respect' up in it only diverts needlessly from the case at hand. In the end we're all 'nerds' trying to improve our favorite tech tool.

curry684 avatar May 27 '22 08:05 curry684

Yesterday, Ryan did work on the things proposed in this issue: https://github.com/symfony/recipes/pull/1090

Let's refocus this issue on the technical discussion, thank you :)

wouterj avatar May 27 '22 09:05 wouterj

I agree with @NMe84 , when doing a new angular project for example, it will let you decide to use which css processor (less, scss, etc) instead of choosing one. It would be nice if Symfony could do the same. :)

cyraid avatar Jan 07 '24 10:01 cyraid

We can close this issue now. The Stimulus integration was removed from the webpack-encore recipe in 2.0 and a new SymfonyStimulusBundle is created (with recipe) to integrate Stimulus in an application.

The webapp skeleton comes with the stimulus bundle installed, as we believe this is a good starting point if you're starting a new webapp in 2024, but you can remove it (which will also remove the asset files related to Stimulus).

Thanks for starting and participating in this discussion!

wouterj avatar Jan 07 '24 12:01 wouterj

I tried removing the stimulus from composer and did update, but still didn't remove the files. I had to manually do it. This still doesn't solve the issue of it coming preinstall does it? Can there not be an option to select which one? (Like angular does when selecting CSS processor)

cyraid avatar Jan 07 '24 13:01 cyraid

Before closing this issue, I tried this myself and the files were removed when uninstalling the stimulus bundle and ux-turbo packages. Maybe you don't have the Symfony Flex Composer plugin installed? If you want more help with this, feel free to ask your question in one of the community support channels.

We prefer not to make the process more complex. Each question during install increases the complexity exponentially for maintenance. Besides that, we also don't want to overwhelm new people by having to make lots of decisions about topics they don't know enough yet to make a good decision.

For this reason, we ship 2 skeletons:

  • symfony new, which is the bare minimal and lets you install whatever more packages you need. This is the expert "let me select which options I want" solution;
  • symfony new --webapp, which is opinionated and helps you get started quicker with a sensible set of packages (but you sometimes need to remove one or more packages depending on your use-case).

wouterj avatar Jan 07 '24 13:01 wouterj

I get it. Any chance for a 3rd option? symfony new --webapp --interactive ? As a new user, I don't know about stimulus, but have used angular. I like all the other opinionated defaults except stimulus. That's why I figure if there was an option to select it at the start (maybe even symfony new --webapp --ux=angular) and such, would give me all the other defaults too.

cyraid avatar Jan 07 '24 13:01 cyraid

* `symfony new --webapp`, which is opinionated and helps you get started quicker with a sensible set of packages (but you sometimes need to remove one or more packages depending on your use-case).

I still don't understand how pre-installing client-side frameworks in general is a "sensible" choice, let alone a package that no one has ever heard of.

I could understand if you were opinionated and chose a framework that a good chunk of people were using, but there is basically no ecosystem for this framework.

I always go for a webapp initialization because other than Stimulus I need everything else in it, and it's incredibly frustrating to always have to go in and manually remove this software bloat. I understand that you don't want too many options but I don't think it's unreasonable at all to at least differentiate between a webapp skeleton that isn't opinionated on the javascript side and one that is, if you absolutely have to push this framework no one uses.

NMe84 avatar Jan 09 '24 01:01 NMe84

To be fair - there has been a lot of changes in Symfony UX and Stimulus since the start of the discussion.

  • Stimulus has a own dedicated packages with recipes. A simple composer remove symfony/stimulus-bundle also removes all the boilerplate.
  • There are integrations for Vue and React (https://ux.symfony.com/)

I feel like Symfony chose a flexible, lightweight and easy to learn framework with Stimulus for those, who don't have any experience in more sophisticated frameworks, providing an good starting point for a lot of basic use cases.

And you probably could create a custom fork of the skeleton, make you own template and use it with composer create-project, since symfony new is more or less just a shorthand for that.

ebitkov avatar Jan 09 '24 07:01 ebitkov

I'll put it this way: even if Stimulus would be the best thing since sliced bread, there is barely any ecosystem for it. No one with any desire for maintainability will want to use it because you'd constantly be having issues with dependencies not being up to date, or with dependencies being written in Vanilla JS, in which case I wonder why you'd even want a framework in the first place.

Besides that, we also don't want to overwhelm new people by having to make lots of decisions about topics they don't know enough yet to make a good decision.

Now you're overwhelming them by installing something most of them won't want (or even recognize) without any explanation of what it is or how to get rid of it, in the skeleton that is meant to get them going more quickly.

NMe84 avatar Jan 09 '24 17:01 NMe84

@NMe84 Like me. I'm the new user of this stimulus stuff, and I had to go out of my way to find out how to get rid of it and what it was. Perhaps if they're not willing to budge with the inclusion, perhaps we could persuade them to include a --without-ux for the --webapp ?

Edit: The removing of the composer items did not work for me to remove the boilerplate.

cyraid avatar Jan 10 '24 02:01 cyraid

I'll put it this way: even if Stimulus would be the best thing since sliced bread, there is barely any ecosystem for it.

Just to clarify: Stimulus is around 10 years old and has been used by the Ruby on Rails community that entire time. It is well-maintained and has a broad ecosystem. You can still choose to not use it - but I didn't want the above comment to mislead people :).

Edit: The removing of the composer items did not work for me to remove the boilerplate.

To help others:

symfony new --webapp without_stimulus
cd without_stimulus
composer remove symfony/stimulus-bundle symfony/ux-turbo

This handles the removal. The only things left are 3 entries in importmap.php. That's a bug in Flex's uninstall script that we should fix :). https://github.com/symfony/flex/issues/1009

weaverryan avatar Jan 10 '24 19:01 weaverryan

To help others:

symfony new --webapp without_stimulus
cd without_stimulus
composer remove symfony/stimulus-bundle symfony/ux-turbo

I'm sorry if this is a stupid question, I never used --webapp, but wouldn't it be simpler to use symfony new without_stimulus then do composer require [some components] instead of adding then removing symfony/stimulus-bundle and symfony/ux-turbo? Is it what you discussed in https://github.com/symfony/recipes/issues/1089#issuecomment-1137631102 ?

alexislefebvre avatar Jan 11 '24 10:01 alexislefebvre

Screenshot 2024-05-10 133632 Screenshot 2024-05-10 133626 Hi everyone, it gives me the error Module not found. in bootstrap.js how I fix this one. because '@hotwired/stimulus' was already pre-install when we installed the new Symfony 7.0 project how its fix?

$ yarn watch yarn run v1.22.19 $ encore dev --watch Running webpack ...

ERROR Failed to compile with 2 errors 10:27:11 am

Module build failed: Module not found: "./assets/bootstrap.js" contains a reference to the file "@symfony/stimulus-bundle". This file can not be found, please check it for typos or update it if the file got moved.

"./assets/bootstrap.js" contains a reference to the file "@symfony/stimulus-bridge/lazy-controller-loader". This file can not be found, please check it for typos or update it if the file got moved.

Entrypoint app/js 15.6 KiB = runtime.js 12.8 KiB app/js.js 2.86 KiB webpack compiled with 2 errors

Raghav9888 avatar May 10 '24 08:05 Raghav9888

Hi @Raghav9888! Please use one of the Symfony support channels for support questions like this. We use the issue tracker purely to track bugs and feature requests.

wouterj avatar May 10 '24 08:05 wouterj