Skip to content

[feat] Implemented a small runtime optimization for SSR #7539

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

Merged
merged 9 commits into from
Feb 27, 2023
Merged
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
4 changes: 4 additions & 0 deletions src/compiler/compile/render_ssr/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Title from './handlers/Title';
import { AppendTarget, CompileOptions } from '../../interfaces';
import { INode } from '../nodes/interfaces';
import { Expression, TemplateLiteral, Identifier } from 'estree';
import { collapse_template_literal } from '../utils/collapse_template_literal';
import { escape_template } from '../utils/stringify';

type Handler = (node: any, renderer: Renderer, options: CompileOptions) => void;
Expand Down Expand Up @@ -106,6 +107,9 @@ export default class Renderer {
this.current = last.current;
}

// Optimize the TemplateLiteral to remove unnecessary nodes
collapse_template_literal(popped.literal);

return popped.literal;
}

Expand Down
34 changes: 34 additions & 0 deletions src/compiler/compile/utils/collapse_template_literal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TemplateLiteral } from 'estree';
import { escape_template } from './stringify';

/**
* Collapse string literals together
*/
export function collapse_template_literal(literal: TemplateLiteral) {
if (!literal.quasis.length) return;

const collapsed_quasis = [];
const collapsed_expressions = [];

let cur_quasi = literal.quasis[0];

// An expression always follows a quasi and vice versa, ending with a quasi
for (let i = 0; i < literal.quasis.length; i++) {
const expr = literal.expressions[i];
const next_quasi = literal.quasis[i + 1];
// If an expression is a simple string literal, combine it with its preceding
// and following quasi
if (next_quasi && expr && expr.type === 'Literal' && typeof expr.value === 'string') {
cur_quasi.value.raw += escape_template(expr.value) + next_quasi.value.raw;
} else {
if (expr) {
collapsed_expressions.push(expr);
}
collapsed_quasis.push(cur_quasi);
cur_quasi = next_quasi;
}
}

literal.quasis = collapsed_quasis;
literal.expressions = collapsed_expressions;
}
6 changes: 6 additions & 0 deletions test/js/samples/collapse-literal-ssr/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
options: {
generate: 'ssr',
dev: true
}
};
25 changes: 25 additions & 0 deletions test/js/samples/collapse-literal-ssr/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* generated by Svelte vX.Y.Z */
import { add_attribute, create_ssr_component, escape } from "svelte/internal";

const const1 = 1;
const const2 = 'const2';

function foo() {
return '';
}

const Component = create_ssr_component(($$result, $$props, $$bindings, slots) => {
return `
<div class="class1 class2" style="color:red;">-</div>


<div${add_attribute("class", const1, 0)}>-</div>
<div${add_attribute("class", const1, 0)}>-</div>


<div class="${"class1 " + escape('class2', true)}">-</div>
<div class="${"class1 " + escape(const2, true)}">-</div>
<div class="${"class1 " + escape(const2, true)}"${add_attribute("style", foo(), 0)}>-</div>`;
});

export default Component;
20 changes: 20 additions & 0 deletions test/js/samples/collapse-literal-ssr/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script>
const const1 = 1;
const const2 = 'const2';

function foo() {
return '';
}
</script>

<!-- canonical case - only markup -->
<div class="class1 class2" style="color:red;">-</div>

<!-- various forms of variable syntax -->
<div class="{const1}">-</div>
<div class={const1}>-</div>

<!-- mixed static string + expressions -->
<div class="class1 {'class2'}">-</div>
<div class="class1 {const2}">-</div>
<div class="class1 {const2}" style={foo()}>-</div>
9 changes: 3 additions & 6 deletions test/validator/samples/assignment-to-const-5/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
"message": "You are assigning to a const",
"start": {
"line": 3,
"column": 1,
"character": 31
"column": 1
},
"end": {
"line": 3,
"column": 33,
"character": 63
},
"pos": 31
"column": 33
}
}
]
9 changes: 3 additions & 6 deletions test/validator/samples/assignment-to-const-7/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
"message": "You are assigning to a const",
"start": {
"line": 3,
"column": 1,
"character": 43
"column": 1
},
"end": {
"line": 3,
"column": 42,
"character": 84
},
"pos": 43
"column": 42
}
}
]