Closed leastbad closed 1 year ago
If we capture the permanent flagged DOM elements during the Reflex init and store references, we can do permanent protection entirely on the client and not even need to send the permanentAttributeName
at all.
I think we can close this for now, as our attention is on building up TurboBoost. We can reopen this if the need arises.
With a major version bump on the horizon, we can take a hard look at our payload sizes. IMO, much of the information that we're passing is redundant. I'm going to do a breakdown here so that we can discuss and share our approach with folks like @joshleblanc and @jonathan-s who write code that interfaces with our data structures.
Note that several points assume that #592 will be merged.
Request
Today:
Details
```ruby { "attrs" => { "class" => "btn btn-dark", "type" => "button", "data-reflex" => "click->example#ping", "data-action" => "click->example#__perform", "data-controller" => "stimulus-reflex", "checked" => false, "selected" => false, "tag_name" => "BUTTON", "value" => "" }, "dataset" => { "dataset" => { "data-reflex" => "click->example#ping", "data-action" => "click->example#__perform" }, "datasetAll" => { } }, "selectors" => [], "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "resolveLate" => false, "suppressLogging" => false, "xpathController" => "//*[@id='poop']/form[1]/button[1]", "xpathElement" => "//*[@id='poop']/form[1]/button[1]", "inner_html" => "", "text_content" => "", "reflexController" => "stimulus-reflex", "permanentAttributeName" => "data-reflex-permanent", "target" => "example#ping", "args" => [], "url" => "http://localhost:3000/", "tabId" => "c146c7c3-7914-4dfb-adc1-5f6e70f57ce4", "version" => "3.5.0-pre9", "params" => { "last_name" => "bad", "bar" => true }, "formData" => "first_name=&last_name=" } ```attrs
: required, don't see how we can get around itdataset
: why do we send this as a separate list? why can't we get it from theattrs
?datasetAll
: propose that we omit this and default to{}
unless it is specifiedselectors
: propose that we omit this and default to[]
unless it is specifiedreflexId
: requiredresolveLate
: will be removed in SR 4suppressLogging
: propose that we omit this and default tofalse
xpathController
: will be removed in SR 4xpathElement
: will be removed in SR 4inner_html
: propose that we rename this toinnerHtml
and omit it and default to""
unless it is specifiedtext_content
: propose that we rename this totextContent
and omit it and default to""
unless it is specifiedreflexController
: propose that we omit this and default tostimulus-reflex
unless it is specifiedpermanentAttributeName
: propose that we omit this and default todata-reflex-permanent
unless it is specifiedtarget
: requiredargs
: propose that we omit this and default to[]
unless it is specifiedurl
: requiredtabId
: requiredversion
: requiredparams
: propose that we omit this and default to{}
unless it is specified or a form is serializedformData
: propose that we omit this and default to""
unless it is specifiedProposed:
Details
```ruby { "attrs" => { "class" => "btn btn-dark", "type" => "button", "data-reflex" => "click->example#ping", "checked" => false, "selected" => false, "tag_name" => "BUTTON", "value" => "" }, "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "target" => "example#ping", "url" => "http://localhost:3000/", "tabId" => "c146c7c3-7914-4dfb-adc1-5f6e70f57ce4", "version" => "3.5.0-pre9" } ```That has to look nicer, no?
Response
Today:
Details
```ruby { "cableReady" => true, "operations" => [ { "value" => 0, "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "selector" => "#my_val", "operation" => "setValue" }, { "name" => "stimulus-reflex:morph-nothing", "selector" => nil, "payload" => { }, "stimulusReflex" => { "attrs" => { "class" => "btn btn-dark", "type" => "button", "data-reflex-serialize-form" => "true", "data-reflex" => "fart->example#ping", "data-action" => "example#ping fart->example#__perform", "data-controller" => "example", "checked" => false, "selected" => false, "tagName" => "BUTTON", "value" => "" }, "dataset" => { "dataset" => { "data-reflex-serialize-form" => "true", "data-reflex" => "fart->example#ping", "data-action" => "example#ping fart->example#__perform", "data-controller" => "example" }, "datasetAll" => { } }, "selectors" => ["body"], "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "resolveLate" => false, "suppressLogging" => false, "xpathController" => "//*[@id='poop']/form[1]/button[1]", "xpathElement" => "//*[@id='poop']/form[1]/button[1]", "innerHtml" => "", "textContent" => "", "reflexController" => "example", "permanentAttributeName" => "data-reflex-permanent", "target" => "example#ping", "args" => [], "url" => "http://localhost:3000/", "tabId" => "c146c7c3-7914-4dfb-adc1-5f6e70f57ce4", "version" => "3.5.0-pre9", "params" => { "lastName" => "bad", "bar" => true }, "formData" => "first_name=&last_name=", "morph" => :nothing }, "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "operation" => "dispatchEvent" } ], "version" => "5.0.0.pre9" } ```With the introduction of the
Reflex
class on the client, there is basically no need to send thestimulusReflex
object back to the client. We are already tracking almost everything in the hash on theReflex
instance. In fact, so far as I can tell, the only thing that is new is themorph
type. Forpage
andselector
morphs,html
,permanent_attribute_name
andchildren_only
are passed as options to CableReady itself.selector
: propose defaulting tonil
payload
: propose defaulting to{}
Note that we might even be able to default the
permanent_attribute_name
todata-reflex-permanent
and save another 45 bytes for every Reflex operation.Proposed:
Details
```ruby { "cableReady" => true, "operations" => [ { "value" => 0, "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "selector" => "#my_val", "operation" => "setValue" }, { "name" => "stimulus-reflex:morph-nothing", "morph" => :nothing, "reflexId" => "22d1b880-417d-4a9b-b4b3-b5339562368f", "operation" => "dispatchEvent" } ], "version" => "5.0.0.pre9" } ```Sign me up!