symfony / stimulus-bridge

Stimulus integration bridge for Symfony projects
https://symfony.com/ux
75 stars 15 forks source link

Load controllers from subdirectory #44

Open devsigner-xyz opened 3 years ago

devsigner-xyz commented 3 years ago

Hello, I am trying to figure out how can I create multiple bootstrap.js files and load controllers from subdirectories, the purpose of this is load only the required JS per context instead of loading all controllers everywhere. I have the feeling that I am missing something but I tried a lot of things and I can't get it to work. Example:

Originally I have bootstrap.js with this content:

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

// Registers Stimulus controllers from controllers.json and in the controllers/ directory
export const app = startStimulusApp(require.context(
    '@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
    true,
    /\.(j|t)sx?$/,
));

This is great, I import bootstrap.js in my entrypoints and I can use stimulus controllers everywhere, but this cause that a lots of unused JS appear in differente bundles, as you can see in the image below, mixitup and intlTelInput should not be there since I used both packages in other context but not in this one.

image

What I want to do is create bootstrap.js files per context to minimize this unused JS but I can't get to work controllers in subdirectories with stimulus-bridge.

// bootstrap_landing.js
import { startStimulusApp } from '@symfony/stimulus-bridge';

export const app = startStimulusApp(require.context(
    '@symfony/stimulus-bridge/lazy-controller-loader!./controllers/landing',
    true,
    /\.(j|t)sx?$/,
));
//landing.js Encore entrypoint
import '../../bootstrap_landing';
// other landing stuff
// bootstrap_extranet.js
import { startStimulusApp } from '@symfony/stimulus-bridge';

export const app = startStimulusApp(require.context(
    '@symfony/stimulus-bridge/lazy-controller-loader!./controllers/extranet',
    true,
    /\.(j|t)sx?$/,
));
// extranet.js Encore entrypoint
import '../../bootstrap_extranet';
// other extranet stuff

By doing this, the final bundle that I have show before should be something like this:

image

trsteel88 commented 3 years ago

I would like to know how to do this as well. My objective is to have the following structure:

Global controllers would be loaded in both frontend and admin. At the moment the only way I can see to create duplicate files within admin/frontend controllers which just import and then export the var from global.

kevinsaul commented 2 years ago

@trsteel88 I have the same need, did you find the way ?

pascalwacker commented 2 years ago

Same here, I've tried it with

export const app = startStimulusApp(require.context(
    '@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
    true,
    /\.(j|t)sx?$/
));
app.load(require.context(
  '@symfony/stimulus-bridge/lazy-controller-loader!../general/controllers',
  true,
  /\.(j|t)sx?$/
));

However, this doesn't register the controllers in the ../general/controllers folder, but instead I get an Uncaught TypeError: constructor is undefined thrown along the stack.

Did anyone find a proper solution for this? My workaround is to create "dummy" controllers... Ex.

// frontend/controllers/foo_controller.js
import Foo_controller from "../../general/controllers/foo_controller";

export default class extends Foo_controller {
}

// general/controllers/foo_controller.js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  connect() {
    console.log('this seams like a really stupid workaround :shrug:');
  }
}
thomas2411 commented 2 years ago

I have the same problem. I would like to load controllers from multiple directories on both assets/controllers as well as vendor/mybundle/Resources/assets/controllers.

ThomasLandauer commented 1 year ago

Thanks to @pascalwacker I found a way: https://stackoverflow.com/q/74448824/1668200