Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit e5d9a9a

Browse files
authored
Hydration (#33)
* Add hydration event support * run hydration for event if component have event listener * bump * prep for release
1 parent 729ecea commit e5d9a9a

File tree

8 files changed

+234
-131
lines changed

8 files changed

+234
-131
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
[![Build Status](https://img.shields.io/travis/com/ryansolid/babel-plugin-jsx-dom-expressions.svg?style=flat)](https://travis-ci.com/ryansolid/babel-plugin-jsx-dom-expressions)
44
[![Coverage Status](https://img.shields.io/coveralls/github/ryansolid/babel-plugin-jsx-dom-expressions.svg?style=flat)](https://coveralls.io/github/ryansolid/babel-plugin-jsx-dom-expressions?branch=master)
55
[![NPM Version](https://img.shields.io/npm/v/babel-plugin-jsx-dom-expressions.svg?style=flat)](https://www.npmjs.com/package/babel-plugin-jsx-dom-expressions)
6-
![](https://img.shields.io/bundlephobia/minzip/babel-plugin-jsx-dom-expressions.svg?style=flat)
76
![](https://img.shields.io/david/ryansolid/babel-plugin-jsx-dom-expressions.svg?style=flat)
87
![](https://img.shields.io/npm/dt/babel-plugin-jsx-dom-expressions.svg?style=flat)
98
[![Gitter](https://img.shields.io/gitter/room/dom-expressions/community)](https://gitter.im/dom-expressions/community)

package-lock.json

+170-115
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "babel-plugin-jsx-dom-expressions",
33
"description": "A JSX to DOM plugin that wraps expressions for fine grained change detection",
4-
"version": "0.14.15",
4+
"version": "0.15.0",
55
"author": "Ryan Carniato",
66
"license": "MIT",
77
"repository": {
@@ -18,16 +18,16 @@
1818
"prepublishOnly": "npm run build"
1919
},
2020
"devDependencies": {
21-
"@babel/core": "7.7.7",
21+
"@babel/core": "7.8.0",
2222
"babel-plugin-tester": "^8.0.1",
2323
"coveralls": "3.0.9",
2424
"dom-expressions": "*",
2525
"jest": "^24.9.0",
26-
"rollup": "^1.27.14",
26+
"rollup": "^1.29.0",
2727
"rollup-plugin-node-resolve": "^5.2.0"
2828
},
2929
"dependencies": {
30-
"@babel/helper-module-imports": "^7.7.4",
31-
"@babel/plugin-syntax-jsx": "^7.7.4"
30+
"@babel/helper-module-imports": "^7.8.0",
31+
"@babel/plugin-syntax-jsx": "^7.8.0"
3232
}
3333
}

src/index.js

+49-9
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,11 @@ export default babel => {
410410
if (child.id) {
411411
registerTemplate(path, child);
412412
if (
413-
!(child.exprs.length || child.dynamics.length) &&
413+
!(
414+
child.exprs.length ||
415+
child.dynamics.length ||
416+
child.postExprs.length
417+
) &&
414418
child.decl.declarations.length === 1
415419
)
416420
return child.decl.declarations[0].init;
@@ -421,7 +425,8 @@ export default babel => {
421425
t.blockStatement([
422426
child.decl,
423427
...child.exprs.concat(
424-
wrapDynamics(path, child.dynamics) || []
428+
wrapDynamics(path, child.dynamics) || [],
429+
child.postExprs || []
425430
),
426431
t.returnStatement(child.id)
427432
])
@@ -648,13 +653,15 @@ export default babel => {
648653
return { exprs, template: "", component: true };
649654
}
650655

651-
function transformAttributes(path, jsx, results) {
656+
function transformAttributes(path, jsx, opts, results) {
652657
let elem = results.id,
658+
hasHydratableEvent = false,
653659
children;
654-
const hasChildren = jsx.children.length > 0;
655660
const spread = t.identifier("_$spread"),
656661
tagName = getTagName(jsx),
657-
isSVG = SVGElements.has(tagName);
662+
isSVG = SVGElements.has(tagName),
663+
hasChildren = jsx.children.length > 0;
664+
658665
jsx.openingElement.attributes.forEach(attribute => {
659666
if (t.isJSXSpreadAttribute(attribute)) {
660667
registerImportMethod(path, "spread");
@@ -673,6 +680,8 @@ export default babel => {
673680
])
674681
)
675682
);
683+
//TODO: generate runtime hydratable event check
684+
hasHydratableEvent = true;
676685
return;
677686
}
678687

@@ -713,6 +722,10 @@ export default babel => {
713722
key !== key.toLowerCase() &&
714723
!NonComposedEvents.has(ev)
715724
) {
725+
// can only hydrate delegated events
726+
hasHydratableEvent = opts.hydratableEvents
727+
? opts.hydratableEvents.includes(ev)
728+
: true;
716729
const events =
717730
path.scope.getProgramParent().data.events ||
718731
(path.scope.getProgramParent().data.events = new Set());
@@ -804,6 +817,8 @@ export default babel => {
804817
if (!hasChildren && children) {
805818
jsx.children.push(children);
806819
}
820+
821+
results.hasHydratableEvent = results.hasHydratableEvent || hasHydratableEvent;
807822
}
808823

809824
function transformChildren(path, jsx, opts, results) {
@@ -832,6 +847,7 @@ export default babel => {
832847
results.decl.push(...child.decl);
833848
results.exprs.push(...child.exprs);
834849
results.dynamics.push(...child.dynamics);
850+
results.hasHydratableEvent = results.hasHydratableEvent || child.hasHydratableEvent;
835851
tempPath = child.id.name;
836852
i++;
837853
} else if (child.exprs.length) {
@@ -924,7 +940,11 @@ export default babel => {
924940
if (child.id) {
925941
registerTemplate(path, child);
926942
if (
927-
!(child.exprs.length || child.dynamics.length) &&
943+
!(
944+
child.exprs.length ||
945+
child.dynamics.length ||
946+
child.postExprs.length
947+
) &&
928948
child.decl.declarations.length === 1
929949
)
930950
return child.decl.declarations[0].init;
@@ -935,7 +955,8 @@ export default babel => {
935955
t.blockStatement([
936956
child.decl,
937957
...child.exprs.concat(
938-
wrapDynamics(path, child.dynamics) || []
958+
wrapDynamics(path, child.dynamics) || [],
959+
child.postExprs || []
939960
),
940961
t.returnStatement(child.id)
941962
])
@@ -961,11 +982,12 @@ export default babel => {
961982
decl: [],
962983
exprs: [],
963984
dynamics: [],
985+
postExprs: [],
964986
isSVG: wrapSVG
965987
};
966988
if (wrapSVG) results.template = "<svg>" + results.template;
967989
if (!info.skipId) results.id = path.scope.generateUidIdentifier("el$");
968-
transformAttributes(path, jsx, results);
990+
transformAttributes(path, jsx, opts, results);
969991
if (
970992
contextToCustomElements &&
971993
(tagName === "slot" || tagName.indexOf("-") > -1)
@@ -986,6 +1008,19 @@ export default babel => {
9861008
transformChildren(path, jsx, opts, results);
9871009
results.template += `</${tagName}>`;
9881010
}
1011+
if (info.topLevel && generate === "hydrate" && results.hasHydratableEvent) {
1012+
registerImportMethod(path, "runHydrationEvents");
1013+
results.postExprs.push(
1014+
t.expressionStatement(
1015+
t.callExpression(t.identifier("_$runHydrationEvents"), [
1016+
t.callExpression(
1017+
t.memberExpression(results.id, t.identifier("getAttribute")),
1018+
[t.stringLiteral("_hk")]
1019+
)
1020+
])
1021+
)
1022+
);
1023+
}
9891024
if (wrapSVG) results.template += "</svg>";
9901025
return results;
9911026
} else if (t.isJSXFragment(jsx)) {
@@ -1056,7 +1091,11 @@ export default babel => {
10561091
if (result.id) {
10571092
registerTemplate(path, result);
10581093
if (
1059-
!(result.exprs.length || result.dynamics.length) &&
1094+
!(
1095+
result.exprs.length ||
1096+
result.dynamics.length ||
1097+
result.postExprs.length
1098+
) &&
10601099
result.decl.declarations.length === 1
10611100
)
10621101
path.replaceWith(result.decl.declarations[0].init);
@@ -1065,6 +1104,7 @@ export default babel => {
10651104
[result.decl].concat(
10661105
result.exprs,
10671106
wrapDynamics(path, result.dynamics) || [],
1107+
result.postExprs || [],
10681108
t.returnStatement(result.id)
10691109
)
10701110
);

test/__hydrate_fixtures__/SVG/output.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { template as _$template } from "r-dom";
22
import { createComponent as _$createComponent } from "r-dom";
3+
import { runHydrationEvents as _$runHydrationEvents } from "r-dom";
34
import { spread as _$spread } from "r-dom";
45
import { wrap as _$wrap } from "r-dom";
56
import { getNextElement as _$getNextElement } from "r-dom";
@@ -49,6 +50,8 @@ const template3 = (function() {
4950

5051
_$spread(_el$5, props, true, false);
5152

53+
_$runHydrationEvents(_el$4.getAttribute("_hk"));
54+
5255
return _el$4;
5356
})();
5457

test/__hydrate_fixtures__/attributeExpressions/output.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { template as _$template } from "r-dom";
22
import { wrap as _$wrap } from "r-dom";
33
import { getNextElement as _$getNextElement } from "r-dom";
4+
import { runHydrationEvents as _$runHydrationEvents } from "r-dom";
45
import { classList as _$classList } from "r-dom";
56
import { spread as _$spread } from "r-dom";
67

@@ -43,6 +44,8 @@ const template = (function() {
4344
return _p$;
4445
});
4546

47+
_$runHydrationEvents(_el$.getAttribute("_hk"));
48+
4649
return _el$;
4750
})();
4851

test/__hydrate_fixtures__/eventExpressions/output.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { template as _$template } from "r-dom";
22
import { delegateEvents as _$delegateEvents } from "r-dom";
33
import { getNextElement as _$getNextElement } from "r-dom";
4+
import { runHydrationEvents as _$runHydrationEvents } from "r-dom";
45

56
const _tmpl$ = _$template(
67
`<div id="main"><button>Click Bound</button><button>Click Delegated</button><button>Click Listener</button></div>`
@@ -20,6 +21,8 @@ const template = (function() {
2021

2122
_el$4.addEventListener("CAPS-ev", () => console.log("custom"));
2223

24+
_$runHydrationEvents(_el$.getAttribute("_hk"));
25+
2326
return _el$;
2427
})();
2528

test/__hydrate_fixtures__/simpleElements/code.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const template = (
22
<div id="main">
3-
<style>{"div { color: red; }"}</style>
3+
<style>{`div { color: red; }`}</style>
44
<h1>Welcome</h1>
55
<label for={"entry"}>Edit:</label>
66
<input id="entry" type="text" />

0 commit comments

Comments
 (0)