Skip to content

SR 4 can safely shrink request and response payload sizes #598

@leastbad

Description

@leastbad

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
{
  "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 it
  • dataset: why do we send this as a separate list? why can't we get it from the attrs?
  • datasetAll: propose that we omit this and default to {} unless it is specified
  • selectors: propose that we omit this and default to [] unless it is specified
  • reflexId: required
  • resolveLate: will be removed in SR 4
  • suppressLogging: propose that we omit this and default to false
  • xpathController: will be removed in SR 4
  • xpathElement: will be removed in SR 4
  • inner_html: propose that we rename this to innerHtml and omit it and default to "" unless it is specified
  • text_content: propose that we rename this to textContent and omit it and default to "" unless it is specified
  • reflexController: propose that we omit this and default to stimulus-reflex unless it is specified
  • permanentAttributeName: propose that we omit this and default to data-reflex-permanent unless it is specified
  • target: required
  • args: propose that we omit this and default to [] unless it is specified
  • url: required
  • tabId: required
  • version: required
  • params: propose that we omit this and default to {} unless it is specified or a form is serialized
  • formData: propose that we omit this and default to "" unless it is specified

Proposed:

Details
{
  "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
{
  "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 the stimulusReflex object back to the client. We are already tracking almost everything in the hash on the Reflex instance. In fact, so far as I can tell, the only thing that is new is the morph type. For page and selector morphs, html, permanent_attribute_name and children_only are passed as options to CableReady itself.

  • selector: propose defaulting to nil
  • payload: propose defaulting to {}

Note that we might even be able to default the permanent_attribute_name to data-reflex-permanent and save another 45 bytes for every Reflex operation.

Proposed:

Details
{
  "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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions