Skip to content

Commit 1d72370

Browse files
Merge pull request #322 from preactjs/jsxssr
2 parents 17f839c + 29f1eef commit 1d72370

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

.changeset/dull-jobs-sin.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'preact-render-to-string': minor
3+
---
4+
5+
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.
6+
7+
```jsx
8+
// input
9+
<div class="foo">hello</div>;
10+
11+
// output
12+
const tpl = [`<div class="foo">hello</div>`];
13+
jsxTemplate(tpl);
14+
```

src/index.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,36 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
182182
// Invoke rendering on Components
183183
if (typeof type === 'function') {
184184
if (type === Fragment) {
185-
// Fragments are the least used components of core that's why
186-
// branching here for comments has the least effect on perf.
187-
if (props.UNSTABLE_comment) {
185+
// Serialized precompiled JSX.
186+
if (props.tpl) {
187+
let out = '';
188+
for (let i = 0; i < props.tpl.length; i++) {
189+
out += props.tpl[i];
190+
191+
if (props.exprs && i < props.exprs.length) {
192+
const value = props.exprs[i];
193+
if (value == null) continue;
194+
195+
// Check if we're dealing with a vnode
196+
if (typeof value === 'object' && value.constructor === undefined) {
197+
out += _renderToString(
198+
value,
199+
context,
200+
isSvgMode,
201+
selectValue,
202+
vnode
203+
);
204+
} else {
205+
// Values are pre-escaped by the JSX transform
206+
out += props.exprs[i];
207+
}
208+
}
209+
}
210+
211+
return out;
212+
} else if (props.UNSTABLE_comment) {
213+
// Fragments are the least used components of core that's why
214+
// branching here for comments has the least effect on perf.
188215
return '<!--' + encodeEntities(props.UNSTABLE_comment || '') + '-->';
189216
}
190217

test/render.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,4 +1650,28 @@ describe('render', () => {
16501650
}
16511651
});
16521652
});
1653+
1654+
describe('precompiled JSX', () => {
1655+
it('should render template', () => {
1656+
let vnode = <Fragment tpl={['<div>foo</div>']} exprs={[]} />;
1657+
let rendered = render(vnode);
1658+
expect(rendered).to.equal('<div>foo</div>');
1659+
});
1660+
1661+
it('should render template with attribute expressions', () => {
1662+
let vnode = (
1663+
<Fragment tpl={['<div ', '>foo</div>']} exprs={['class="foo"']} />
1664+
);
1665+
let rendered = render(vnode);
1666+
expect(rendered).to.equal('<div class="foo">foo</div>');
1667+
});
1668+
1669+
it('should render template with child expressions', () => {
1670+
let vnode = (
1671+
<Fragment tpl={['<div>foo', '</div>']} exprs={[<span>bar</span>]} />
1672+
);
1673+
let rendered = render(vnode);
1674+
expect(rendered).to.equal('<div>foo<span>bar</span></div>');
1675+
});
1676+
});
16531677
});

0 commit comments

Comments
 (0)