Skip to content

Commit

Permalink
Merge pull request #322 from preactjs/jsxssr
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister committed Nov 7, 2023
2 parents 17f839c + 29f1eef commit 1d72370
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 3 deletions.
14 changes: 14 additions & 0 deletions .changeset/dull-jobs-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'preact-render-to-string': minor
---

Add support for precompiled JSX transform, see https://deno.com/blog/v1.38#fastest-jsx-transform. Compared to traditional JSX transforms, the precompiled JSX transform tries to pre-serialize as much of the JSX as possible. That way less objects need to be created and serialized which relieves a lot of GC pressure.

```jsx
// input
<div class="foo">hello</div>;

// output
const tpl = [`<div class="foo">hello</div>`];
jsxTemplate(tpl);
```
33 changes: 30 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,36 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
// Invoke rendering on Components
if (typeof type === 'function') {
if (type === Fragment) {
// Fragments are the least used components of core that's why
// branching here for comments has the least effect on perf.
if (props.UNSTABLE_comment) {
// Serialized precompiled JSX.
if (props.tpl) {
let out = '';
for (let i = 0; i < props.tpl.length; i++) {
out += props.tpl[i];

if (props.exprs && i < props.exprs.length) {
const value = props.exprs[i];
if (value == null) continue;

// Check if we're dealing with a vnode
if (typeof value === 'object' && value.constructor === undefined) {
out += _renderToString(
value,
context,
isSvgMode,
selectValue,
vnode
);
} else {
// Values are pre-escaped by the JSX transform
out += props.exprs[i];
}
}
}

return out;
} else if (props.UNSTABLE_comment) {
// Fragments are the least used components of core that's why
// branching here for comments has the least effect on perf.
return '<!--' + encodeEntities(props.UNSTABLE_comment || '') + '-->';
}

Expand Down
24 changes: 24 additions & 0 deletions test/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1650,4 +1650,28 @@ describe('render', () => {
}
});
});

describe('precompiled JSX', () => {
it('should render template', () => {
let vnode = <Fragment tpl={['<div>foo</div>']} exprs={[]} />;
let rendered = render(vnode);
expect(rendered).to.equal('<div>foo</div>');
});

it('should render template with attribute expressions', () => {
let vnode = (
<Fragment tpl={['<div ', '>foo</div>']} exprs={['class="foo"']} />
);
let rendered = render(vnode);
expect(rendered).to.equal('<div class="foo">foo</div>');
});

it('should render template with child expressions', () => {
let vnode = (
<Fragment tpl={['<div>foo', '</div>']} exprs={[<span>bar</span>]} />
);
let rendered = render(vnode);
expect(rendered).to.equal('<div>foo<span>bar</span></div>');
});
});
});

0 comments on commit 1d72370

Please sign in to comment.