Comments (11)
Do explore that in Turbo
The dynamic loading of the stimulus controllers occurs in the stimulus-loading.js
library in this codebase. Would it then make more sense to include the logic in the library which dynamically loads the stimulus controllers?
Basing it off this closed PR created by @seanpdoyle, the following modifications dispatches an event stimulus:ready
which solves the issue for us:
function loadController(name, under, application) {
if (!(name in registeredControllers)) {
+ registeredControllers[name] = false
import(controllerFilename(name, under))
.then(module => registerController(name, module, application))
- .catch(error => console.error(`Failed to autoload controller: ${name}`, error))
+ .catch(error => importError(error, name))
+ .finally(() => dispatchWhenReady())
}
}
function registerController(name, module, application) {
- if (!(name in registeredControllers)) {
+ if (!registeredControllers[name]) {
application.register(name, module.default)
registeredControllers[name] = true
}
}
+ function importError(error, name) {
+ delete registeredControllers[name]
+ console.error(`Failed to autoload controller: ${name}`, error)
+ }
+ function dispatchWhenReady() {
+ if(Object.values(registeredControllers).every(Boolean)) {
+ const controllers = Object.keys(registeredControllers);
+ const event = new CustomEvent('stimulus:ready', { detail: { controllers }, bubbles: true });
+ document.dispatchEvent(event);
+ }
+ }
from stimulus-rails.
Hmm, not an easy problem to solve, because lazy loading is loading things dynamically. So some controllers might have been loaded already, and good to go. Others only load when new HTML appears that have them in there.
Seems like what we need is essentially turbo:finish or something like that which captures all forms of turbo loading. Do explore that in Turbo 👍
from stimulus-rails.
Actually, yes, I do like that option too. I was thinking of turbo:finish
, which I also think we should explore. But I'd take the stimulus:ready
event too. That's a good idea.
from stimulus-rails.
Hello @dhh @tleish – Is there any continued interest on this one?
I also would be quite interested in a stimulus:ready
event (per controller), and perhaps a turbo:finish
(once all loading complete). I checked out stimulus-loading.js
and I didn't see an event emitted.
On our application, we've moved to lazyLoadControllersFrom
for performance reasons, but are noticing a 300–700ms delay from seeing HTML to the page actually being ready for interaction (controllers loaded).
Of course, it could be because we're still loading much unnecessary JS prior to MutationObserver
kicking in effect, so maybe it's a "main thread blocked for too long" issue.
In any case, stimulus emitting such an event on lazy load would help validate any hypothesis/diagnostic.
from stimulus-rails.
I'm actually starting to think that maybe we shouldn't lazy load at all. That it just makes things too complicated. The majority of apps should just preload all controllers. And the ones who can't do that can just have different includes per page. I think scanning the HTML to lazy load is too clever, too slow, and too error prone.
We already changed the default to eager loading.
from stimulus-rails.
it just makes things too complicated
@dhh - Curious what problems you are running into. We occasionally need to handle order dependencies of cross-controller communication using lazy loading, but it hasn't been a major issue.
We see quite a difference in performance initial page load when testing using speed test using lighthouse, we see numbers like:
- eager load: 68 lighthouse performance score
- lazy load: 95 lighthouse performance score
from stimulus-rails.
Problem is attachment timing. When there are things in the DOM that need to change from a controller. I seem to remember us getting visual jitter from it.
Haven't seen anything like that on lighthouse score differences. Is that a CDN issue maybe?
from stimulus-rails.
Numbers posted above are just from running localhots. Only difference between the to runs is the use of @hotwired/stimulus-loading#eagerLoadControllersFrom
vs @hotwired/stimulus-loading#lazyLoadControllersFrom
from stimulus-rails.
Gotcha. If you actually need those controllers loaded, and they operate on the DOM, I think that difference is artificial.
from stimulus-rails.
We have lots of stimulus controllers and js libraries. We need a portion of the controllers for a given page, but not all of them.
For example, I see hey.com has over 230 js modules, with over 150 of them as controllers. Managing which controller to load on which page seems like a pain. Loading all 230 files on every page load also seems overkill, even with http2. Dynamically lazy loading the modules as they are used in the DOM makes it so much easier from a development perspective, cleaner and faster from a user/browser loading experience. Especially when some of those controllers might include large js modules.
I assume this is why hey.com also uses lazyloading:
/* app.hey.com/assets/controllers/index.js */
import { application } from "controllers/application"
import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
lazyLoadControllersFrom("controllers", application)
It's a slick strategy.
from stimulus-rails.
from stimulus-rails.
Related Issues (20)
- Controllers written in Coffeescript? HOT 1
- why not auto "rails stimulus:manifest:update"
- Failing to register controllers does not bubble the error to handleError HOT 1
- stimulus-rails installation rails - undefined method Stimulus::Rails.application HOT 1
- manifest:update configuration for controller segmentation HOT 1
- Should controller names be registered as camelCase? HOT 2
- rails stimulus:manifest:update replacing our index.js configs HOT 1
- 404 on assets/stimulus-loading.js with config.assets.digest set to false HOT 11
- Mutation Observer not recognising DOM change when using Turbo Streams HOT 2
- Browser Back button is not working for some feature in stimulus HOT 2
- Console error with lazyLoadControllersFrom and external controller HOT 1
- Add typescript support for rails stimulus generator
- Action params not populating HOT 1
- Debugging `Failed to auto-load controller` ... `Unable to resolve specifier` HOT 2
- Error when passing JSON formatted data from rails to stimulus HOT 1
- Stimulus broken in Firefox 115+ with importmap-rails HOT 4
- Is it possible to use controllers stored in a GEM ?
- ActiveModel not working with value to Object HOT 2
- Add stimulus:manifest:update to the tasks description HOT 1
- Error in lib/install/stimulus_with_node.rb
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stimulus-rails.