ux icon indicating copy to clipboard operation
ux copied to clipboard

[StimulusBundle] Conditional Loading of Stimulus Controllers Based on Configuration

Open Jamie-Vandenbalck opened this issue 1 year ago • 7 comments

Background

I am currently working on a Symfony application that has distinct sections for customers and administrators. Each section has its own set of Stimulus controllers. The problem I face is that when I configure controllers to be eagerly loaded, all controllers are loaded across both the customer and admin sides. This leads to unnecessary loading and potential performance issues.

Current Situation

The Symfony StimulusBundle loads controllers either eagerly or lazily, but this is configured globally or through static annotations (/* stimulusFetch: eager */). There is currently no built-in mechanism to conditionally load controllers based on configuration or environment.

Problem Statement

In my application:

  1. I have controllers specific to the customer side and controllers specific to the admin side.
  2. I do not want customer-side controllers to load eagerly in the admin interface and vice versa.
  3. Managing controller loading globally results in increased load times and resource usage, as unnecessary controllers are loaded.

Proposed Feature

I propose adding a feature to the StimulusBundle that allows splitting of Stimulus controllers based on configuration settings. This would enable developers to specify which controllers should be loaded in different contexts (e.g., customer or admin).

Suggested Implementation

  1. Configuration Key:
  • Add a configuration option in stimulus.yaml to specify different groups of controllers.
  • Example:
# config/packages/stimulus.yaml
stimulus:
  controller_paths:
    app:
      - '%kernel.project_dir%/assets/controllers/app'
    admin:
      - '%kernel.project_dir%/assets/controllers/admin'
  1. StimulusBundle Logic:
  • Modify the StimulusBundle to read from the configuration and conditionally register controllers based on the context or environment.
  • Implement logic to detect the current context and load the appropriate set of controllers.
// assets/bootstrap.js

import { startStimulusApp } from '@symfony/stimulus-bundle';

const app = startStimulusApp('app');

Benefits

  1. Performance Optimization: Only the necessary controllers are loaded for the given context, reducing load times and resource usage.
  2. Improved Maintainability: Easier to manage controllers and configurations for different parts of the application.
  3. Flexibility: Developers can configure which controllers should be loaded eagerly or lazily based on their application’s needs.

Example Use Case

  1. A Symfony application with a customer-facing site and an admin dashboard.
  2. The customer side only needs controllers like home_controller and product_controller.
  3. The admin side requires controllers like dashboard_controller and user_management_controller.
  4. With this feature, developers could specify eager loading only for the relevant controllers for each side, avoiding cross-loading and maintaining a lean asset load.

Jamie-Vandenbalck avatar Nov 01 '24 20:11 Jamie-Vandenbalck

To eager load some controllers, you can register them manually in Stimulus application (using distinct endpoints, calling different bootstrap.js files for admin/front)

// assets/bootstrap.js

import { startStimulusApp } from '@symfony/stimulus-bundle';
import Clipboard from 'stimulus-clipboard';
+ // import your admin controllers here

const app = startStimulusApp();

app.register('clipboard', Clipboard);
+ // register them here

I agree there is something a bit "all or nothing" with lazy controllers for now, but making changes here could reveal itself more complex than it seems.

I'll have a look in december :)

smnandre avatar Nov 02 '24 15:11 smnandre

(only talking about AssetMapper here, but i guess the solution will be very similar with WebPack)

Currently, a new Symfony webapp contains this bootstrap.js file

import { startStimulusApp } from '@symfony/stimulus-bundle';

const app = startStimulusApp();
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

In the @symfony/stimulus-bundle file, the controller.json is hardcoded and it will not be easy to change this

(the Stimulus Bundle is now provided with any new install of Symfony, so we must be extra-cautious about any change that could break any app in the wild)

Currentyl the Stimulus Bundle has no capacity to handle to "apps" or "packages" in a given project, and all the controllers are referenced in this controller.js file, compiled on the fly during asset mapper / importmap compilations.

So here we could start by addind a new way to generate distinct "application configuration" (and then implement related controller loaders)

So something like this

# config/packages/asset_mapper.yaml      # or asset_mapper ?

stimulus:
    controller_paths:
        - '%kernel.project_dir%/assets/controllers/'
        
    application:      # or any name
    
        admin:         # we need a unique slug name here
            controller_paths: 
                - '%kernel.project_dir%/assets/admin/controllers'
     
       front:     
           controller_paths: 
                - '%kernel.project_dir%/assets/front/controllers'  

Then you would create two entrypoints (admin and front) in your importmap configuration, in which you would import "aliased" applications.

// assets/admin.js

// magic import configured with admin controllers (eager + lazy)
import { startStimulusApp } from '@symfony/stimulus-bundle/admin';

Configuring the lazyness depending on the group seems to me a bit too specific to your use case, but would the previous ideas suit your needs ?

smnandre avatar Nov 02 '24 19:11 smnandre

Thank you for opening this discussion and for the workaround suggestion. I fully support the idea of conditionally loading Stimulus controllers based on configuration to improve performance, especially for applications like mine with separate customer and admin sections. Configuring controller groups in stimulus.yaml as proposed would be ideal.

Jamie-Vandenbalck avatar Nov 05 '24 11:11 Jamie-Vandenbalck

Hello @smnandre @Jamie-Vandenbalck , I tried to do this, but it doesn't work. Is it feasible, or is it just a suggestion? I would also like to have this feature.

mahery01 avatar Mar 18 '25 08:03 mahery01

Thank you for this suggestion. There has not been a lot of activity here for a while. Would you still like to see this feature? Every feature is developed by the community. Perhaps someone would like to try? You can read how to contribute to get started.

carsonbot avatar Sep 19 '25 12:09 carsonbot

Friendly ping? Should this still be open? I will close if I don't hear anything.

carsonbot avatar Oct 03 '25 12:10 carsonbot

Friendly ping? Should this still be open? I will close if I don't hear anything.

Yes, I’d still like this feature. Please keep it open.

Jamie-Vandenbalck avatar Oct 04 '25 13:10 Jamie-Vandenbalck