Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: serialize data as strings, reduce bytes per flush #1551

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions packages/marko/src/runtime/components/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use strict";

var warp10 = require("warp10");
var safeJSONRegExp = /<\/|\u2028|\u2029/g;
var safeJSONStringRegExp = /'|\\|<\/script|\u2028|\u2029/g;
var IGNORE_GLOBAL_TYPES = new Set(["undefined", "function", "symbol"]);
var DEFAULT_RUNTIME_ID = "M";

Expand All @@ -10,11 +10,18 @@ var FLAG_HAS_RENDER_BODY = 2;
var FLAG_IS_LEGACY = 4;
var FLAG_OLD_HYDRATE_NO_CREATE = 8;

function safeJSONReplacer(match) {
if (match === "</") {
return "\\u003C/";
} else {
return "\\u" + match.charCodeAt(0).toString(16);
function safeStringJSONReplacer(match) {
switch (match) {
case "'":
return "\\'";
case "\\":
return "\\\\";
case "</script":
return "<\\/script";
case "\u2028":
return "\\u2028";
case "\u2029":
return "\\u2029";
}
}

Expand All @@ -30,8 +37,8 @@ function isNotEmpty(obj) {
}
function safeStringify(data) {
return JSON.stringify(warp10.stringifyPrepare(data)).replace(
safeJSONRegExp,
safeJSONReplacer
safeJSONStringRegExp,
safeStringJSONReplacer
);
}

Expand Down Expand Up @@ -273,13 +280,9 @@ exports.___getInitComponentsCode = function getInitComponentsCode(
return "";
}

const runtimeId = out.global.runtimeId;
const componentGlobalKey =
runtimeId === DEFAULT_RUNTIME_ID ? "MC" : runtimeId + "_C";

return `$${componentGlobalKey}=(window.$${componentGlobalKey}||[]).concat(${safeStringify(
return `JSON.${out.global.runtimeId}+=',${safeStringify(
initComponentsData
)})`;
)}'`;
};

exports.___addComponentsFromContext = addComponentsFromContext;
Expand Down
41 changes: 15 additions & 26 deletions packages/marko/src/runtime/components/init-components-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
var complain = "MARKO_DEBUG" && require("complain");
var warp10Finalize = require("warp10/finalize");
var eventDelegation = require("./event-delegation");
var win = window;
var defaultDocument = document;
var createFragmentNode = require("../vdom/morphdom/fragment")
.___createFragmentNode;
Expand Down Expand Up @@ -252,41 +251,31 @@ function initClientRendered(componentDefs, doc) {
* This method initializes all components that were rendered on the server by iterating over all
* of the component IDs.
*/
function initServerRendered(renderedComponents, doc) {
function initServerRendered(renderedComponents, doc, runtimeId) {
var type = typeof renderedComponents;
var globalKey = "$";
var runtimeId;

if (type !== "object") {
if (type === "string") {
runtimeId = renderedComponents;
globalKey += runtimeId + "_C";
} else {
globalKey += (runtimeId = DEFAULT_RUNTIME_ID) + "C";
}

renderedComponents = win[globalKey];

var fakeArray = (win[globalKey] = {
r: runtimeId,
concat: initServerRendered
runtimeId = renderedComponents || DEFAULT_RUNTIME_ID;
renderedComponents = JSON[runtimeId];
Object.defineProperty(JSON, runtimeId, {
configurable: true,
set: function(v) {
initServerRendered(JSON.parse(v.slice(10)), doc, runtimeId);
}
});

if (renderedComponents && renderedComponents.forEach) {
renderedComponents.forEach(function(renderedComponent) {
fakeArray.concat(renderedComponent);
if (renderedComponents) {
JSON.parse("[" + renderedComponents.slice(10) + "]").forEach(function(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this — it looks like in the future it could even throttle itself based on how much distress the user’s CPU is in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that was one of the things I liked as well, we can lazily parse the JSON.

renderedComponent
) {
initServerRendered(renderedComponent, doc, runtimeId);
});
}

return fakeArray;
return;
}

var isFromSerializedGlobals = this.concat === initServerRendered;

if (isFromSerializedGlobals) {
runtimeId = this.r;
doc = defaultDocument;
} else {
if (!runtimeId) {
runtimeId = renderedComponents.r || DEFAULT_RUNTIME_ID;

// eslint-disable-next-line no-constant-condition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var expect = require("chai").expect;

it("should serialize component input down to the browser", function() {
expect(window.$test_C).to.not.equal(undefined);
expect(JSON.test).to.not.equal(undefined);
expect(window.fooComponent).equal(undefined);
window.$initComponents("test");

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><body><!--FLUSH--><div class="inner"><div class="inner-inner"><!--M#s0-7--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-8--><div>Hello inner</div><!--M/--></div><!--M#s0-9--><div>Hello outer</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-8",0,{"name":"inner"},{"f":1}],["s0-7",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await-beginAsync/components/hello/index.marko"]})</script></body></html>
<html><body><!--FLUSH--><div class="inner"><div class="inner-inner"><!--M#s0-7--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-8--><div>Hello inner</div><!--M/--></div><!--M#s0-9--><div>Hello outer</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-8",0,{"name":"inner"},{"f":1}],["s0-7",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await-beginAsync/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><head><title><!--FLUSH-->Welcome Frank</title></head><body><!--M#s0-0-5-5--><div>Hello</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-0-5-5",0,{},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await-title/components/hello/index.marko"]})</script></body></html>
<html><head><title><!--FLUSH-->Welcome Frank</title></head><body><!--M#s0-0-5-5--><div>Hello</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-0-5-5",0,{},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await-title/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><body><!--FLUSH--><div class="inner"><!--FLUSH--><div class="inner-inner"><!--M#s0-8--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-9--><div>Hello inner</div><!--M/--></div><!--M#s0-10--><div>Hello outer</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-8",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"inner"},{"f":1}],["s0-10",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await/components/hello/index.marko"]})</script></body></html>
<html><body><!--FLUSH--><div class="inner"><!--FLUSH--><div class="inner-inner"><!--M#s0-8--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-9--><div>Hello inner</div><!--M/--></div><!--M#s0-10--><div>Hello outer</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-8",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"inner"},{"f":1}],["s0-10",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures-async-deprecated/components-await/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!--M#s0--><!DOCTYPE html><html lang="en"><body>Hello <script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0",0,{"foo-0":"bar\u2028","foo-1":"bar\u2029","foo-2":"\u2028bar\u2029","foo-3":"Hello \u003C/script> \u2028bar\u2029"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/component-safe-json/template.marko"]})</script></body></html><!--M/-->
<!--M#s0--><!DOCTYPE html><html lang="en"><body>Hello <script>JSON.M+=',{"l":1,"w":[["s0",0,{"foo-0":"bar\u2028","foo-1":"bar\u2029","foo-2":"\u2028bar\u2029","foo-3":"Hello <\/script> \u2028bar\u2029"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/component-safe-json/template.marko"]}'</script></body></html><!--M/-->
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><body><!--FLUSH--><div class="inner"><div class="inner-inner"><!--M#s0-7--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-8--><div>Hello inner</div><!--M/--></div><!--M#s0-9--><div>Hello outer</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-8",0,{"name":"inner"},{"f":1}],["s0-7",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await-beginAsync/components/hello/index.marko"]})</script></body></html>
<html><body><!--FLUSH--><div class="inner"><div class="inner-inner"><!--M#s0-7--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-8--><div>Hello inner</div><!--M/--></div><!--M#s0-9--><div>Hello outer</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-8",0,{"name":"inner"},{"f":1}],["s0-7",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await-beginAsync/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><head><title><!--FLUSH-->Welcome Frank</title></head><body><!--M#s0-0-5-5--><div>Hello</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-0-5-5",0,{},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await-title/components/hello/index.marko"]})</script></body></html>
<html><head><title><!--FLUSH-->Welcome Frank</title></head><body><!--M#s0-0-5-5--><div>Hello</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-0-5-5",0,{},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await-title/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><body><!--FLUSH--><div class="inner"><!--FLUSH--><div class="inner-inner"><!--M#s0-8--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-9--><div>Hello inner</div><!--M/--></div><!--M#s0-10--><div>Hello outer</div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-8",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"inner"},{"f":1}],["s0-10",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await/components/hello/index.marko"]})</script></body></html>
<html><body><!--FLUSH--><div class="inner"><!--FLUSH--><div class="inner-inner"><!--M#s0-8--><div>Hello inner-inner</div><!--M/--></div><!--M#s0-9--><div>Hello inner</div><!--M/--></div><!--M#s0-10--><div>Hello outer</div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-8",0,{"name":"inner-inner"},{"f":1}],["s0-9",0,{"name":"inner"},{"f":1}],["s0-10",0,{"name":"outer"},{"f":1}]],"t":["/marko-test$1.0.0/render/fixtures/components-await/components/hello/index.marko"]}'</script></body></html>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html><head>Components</head><body><!--M#s0-3--><div><h1>foo1</h1><div><h1>bar1</h1></div><div><h1>bar2</h1></div><div><h1>foo-split1</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div><div><h1>foo-split2</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div></div><!--M/--><!--M#s0-4--><div><h1>foo2</h1><div><h1>bar1</h1></div><div><h1>bar2</h1></div><div><h1>foo-split1</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div><div><h1>foo-split2</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div></div><!--M/--><!--M#s0-5--><div><h1>split1</h1><!--M^s0-5-split-child1 s0-5 split-child1--><div><h1>split-child1</h1></div><!--M/--><!--M^s0-5-split-child2 s0-5 split-child2--><div><h1>split-child2</h1></div><!--M/--></div><!--M/--><!--M#s0-6--><div><h1>split2</h1><!--M^s0-6-split-child1 s0-6 split-child1--><div><h1>split-child1</h1></div><!--M/--><!--M^s0-6-split-child2 s0-6 split-child2--><div><h1>split-child2</h1></div><!--M/--></div><!--M/--><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-3",0,{"name":"foo1"},{"f":1}],["s0-4",0,{"name":"foo2"},{"f":1}],["s0-5",1,{"name":"split1"}],["s0-5-split-child1",2,{"name":"split-child1"}],["s0-5-split-child2",2,{"name":"split-child2"}],["s0-6",1,{"name":"split2"}],["s0-6-split-child1",2,{"name":"split-child1"}],["s0-6-split-child2",2,{"name":"split-child2"}]],"t":["/marko-test$1.0.0/render/fixtures/components/components/foo/index.marko","/marko-test$1.0.0/render/fixtures/components/components/split/component-browser","/marko-test$1.0.0/render/fixtures/components/components/split/components/split-child/component-browser"]})</script></body></html>
<html><head>Components</head><body><!--M#s0-3--><div><h1>foo1</h1><div><h1>bar1</h1></div><div><h1>bar2</h1></div><div><h1>foo-split1</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div><div><h1>foo-split2</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div></div><!--M/--><!--M#s0-4--><div><h1>foo2</h1><div><h1>bar1</h1></div><div><h1>bar2</h1></div><div><h1>foo-split1</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div><div><h1>foo-split2</h1><div><h1>split-child1</h1></div><div><h1>split-child2</h1></div></div></div><!--M/--><!--M#s0-5--><div><h1>split1</h1><!--M^s0-5-split-child1 s0-5 split-child1--><div><h1>split-child1</h1></div><!--M/--><!--M^s0-5-split-child2 s0-5 split-child2--><div><h1>split-child2</h1></div><!--M/--></div><!--M/--><!--M#s0-6--><div><h1>split2</h1><!--M^s0-6-split-child1 s0-6 split-child1--><div><h1>split-child1</h1></div><!--M/--><!--M^s0-6-split-child2 s0-6 split-child2--><div><h1>split-child2</h1></div><!--M/--></div><!--M/--><script>JSON.M+=',{"l":1,"w":[["s0-3",0,{"name":"foo1"},{"f":1}],["s0-4",0,{"name":"foo2"},{"f":1}],["s0-5",1,{"name":"split1"}],["s0-5-split-child1",2,{"name":"split-child1"}],["s0-5-split-child2",2,{"name":"split-child2"}],["s0-6",1,{"name":"split2"}],["s0-6-split-child1",2,{"name":"split-child1"}],["s0-6-split-child2",2,{"name":"split-child2"}]],"t":["/marko-test$1.0.0/render/fixtures/components/components/foo/index.marko","/marko-test$1.0.0/render/fixtures/components/components/split/component-browser","/marko-test$1.0.0/render/fixtures/components/components/split/components/split-child/component-browser"]}'</script></body></html>