diff --git a/benchmarks.js b/benchmarks.js
index 84c5e87..a3a5b88 100644
--- a/benchmarks.js
+++ b/benchmarks.js
@@ -13,6 +13,7 @@ var enabledBenchmarks = null;
enabledLibs = {
marko: true,
preact: true,
+ hyperapp: true,
react: true,
vue: true,
inferno: true
@@ -75,4 +76,4 @@ Object.keys(enabledBenchmarks).forEach((benchmarkName) => {
});
});
-module.exports = benchmarks;
\ No newline at end of file
+module.exports = benchmarks;
diff --git a/benchmarks/color-picker/hyperapp/.babelrc b/benchmarks/color-picker/hyperapp/.babelrc
new file mode 100644
index 0000000..607530b
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/.babelrc
@@ -0,0 +1,8 @@
+{
+ "presets": [
+ ["es2015", { "loose": true, "modules": false }]
+ ],
+ "plugins": [
+ ["transform-react-jsx", { "pragma": "h" }]
+ ]
+}
diff --git a/benchmarks/color-picker/hyperapp/client.jsx b/benchmarks/color-picker/hyperapp/client.jsx
new file mode 100644
index 0000000..1418c00
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/client.jsx
@@ -0,0 +1,29 @@
+const { app } = require('hyperapp');
+const { state, actions, view } = require('./components/App');
+
+const mountNode = document.getElementById('mount');
+
+if (mountNode) {
+ const initialState = Object.assign({}, state, { colors: window.colors });
+ app(initialState, actions, view, mountNode);
+ console.log('Re-rendering on client completed');
+}
+
+window.addBench('hyperapp', (el, colors) => {
+ const initialState = Object.assign({}, state, { colors });
+
+ let currentDone;
+ const appActions = Object.assign({}, actions, {
+ onUpdate() {
+ currentDone();
+ }
+ });
+
+ const widget = app(initialState, appActions, view, el);
+
+ let selectedColorIndex = 0;
+ return (done) => {
+ widget.setColorIndex((++selectedColorIndex) % colors.length);
+ currentDone = done;
+ };
+});
diff --git a/benchmarks/color-picker/hyperapp/components/App.jsx b/benchmarks/color-picker/hyperapp/components/App.jsx
new file mode 100644
index 0000000..b4c54d4
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/components/App.jsx
@@ -0,0 +1,54 @@
+const { h } = require('hyperapp');
+
+const state = {
+ selectedColorIndex: 0,
+ colors: [],
+};
+
+const actions = {
+ setColorIndex(selectedColorIndex) {
+ return { selectedColorIndex };
+ },
+ onUpdate() {
+ // for benchmark
+ },
+};
+
+function renderColors(state, actions) {
+ if (state.colors.length) {
+ return (
+
+ {state.colors.map((color, index) => (
+ - actions.setColorIndex(index)
+ }>
+ {color.name}
+
+ ))}
+
+ );
+ } else {
+ return No colors!
+ }
+}
+
+function view(state, actions) {
+ const currentColor = state.colors[state.selectedColorIndex];
+ return (
+
+
Choose your favorite color:
+
+ {renderColors(state, actions)}
+
+
You chose:
{currentColor.name}
+
+ );
+}
+
+module.exports = {
+ state,
+ actions,
+ view,
+};
diff --git a/benchmarks/color-picker/hyperapp/page.marko b/benchmarks/color-picker/hyperapp/page.marko
new file mode 100644
index 0000000..2380339
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/page.marko
@@ -0,0 +1,23 @@
+import serverRender from './util/serverRender';
+import App from './components/App';
+
+
+ <@body>
+ $ var renderedHTML = serverRender(App, input.colors);
+ $!{renderedHTML}
+
+
+ @body>
+
diff --git a/benchmarks/color-picker/hyperapp/rollup.config.js b/benchmarks/color-picker/hyperapp/rollup.config.js
new file mode 100644
index 0000000..0b8c8d0
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/rollup.config.js
@@ -0,0 +1,25 @@
+import commonjsPlugin from 'rollup-plugin-commonjs';
+import browserifyPlugin from 'rollup-plugin-browserify-transform';
+import nodeResolvePlugin from 'rollup-plugin-node-resolve';
+import babelPlugin from 'rollup-plugin-babel';
+import envify from 'envify';
+import path from 'path';
+
+process.env.NODE_ENV = 'production';
+
+export default {
+ input: path.resolve(__dirname, 'client.jsx'),
+ output: {
+ format: 'iife',
+ file: path.join(process.env.BUNDLES_DIR, 'hyperapp.js')
+ },
+ mame: 'app',
+ plugins: [
+ babelPlugin({
+ exclude: 'node_modules/**'
+ }),
+ browserifyPlugin(envify),
+ nodeResolvePlugin(),
+ commonjsPlugin()
+ ],
+};
diff --git a/benchmarks/color-picker/hyperapp/server.jsx b/benchmarks/color-picker/hyperapp/server.jsx
new file mode 100644
index 0000000..c906a79
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/server.jsx
@@ -0,0 +1,10 @@
+const { app } = require('hyperapp');
+const { renderToString } = require('hyperapp-render');
+const { state, actions, view } = require('./components/App');
+
+module.exports = function(colors) {
+ return function benchFn() {
+ const initialState = Object.assign({}, state, { colors });
+ return renderToString(view(initialState, actions));
+ };
+};
diff --git a/benchmarks/color-picker/hyperapp/util/serverRender.jsx b/benchmarks/color-picker/hyperapp/util/serverRender.jsx
new file mode 100644
index 0000000..5bd9d9b
--- /dev/null
+++ b/benchmarks/color-picker/hyperapp/util/serverRender.jsx
@@ -0,0 +1,6 @@
+const { renderToString } = require('hyperapp-render');
+
+module.exports = function infernoRender(App, colors) {
+ const state = Object.assign({}, App.state, { colors });
+ return renderToString(App.view(state, App.actions));
+};
diff --git a/benchmarks/search-results/hyperapp/.babelrc b/benchmarks/search-results/hyperapp/.babelrc
new file mode 100644
index 0000000..607530b
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/.babelrc
@@ -0,0 +1,8 @@
+{
+ "presets": [
+ ["es2015", { "loose": true, "modules": false }]
+ ],
+ "plugins": [
+ ["transform-react-jsx", { "pragma": "h" }]
+ ]
+}
diff --git a/benchmarks/search-results/hyperapp/client.jsx b/benchmarks/search-results/hyperapp/client.jsx
new file mode 100644
index 0000000..c2d5b68
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/client.jsx
@@ -0,0 +1,30 @@
+const { app } = require('hyperapp');
+const { state, actions, view } = require('./components/App');
+
+const mountNode = document.getElementById('searchResultsMount');
+
+if (mountNode) {
+ const initialState = Object.assign({}, state, { colors: window.searchResultsData });
+ app(initialState, actions, view, mountNode);
+ console.log('Re-rendering on client completed');
+}
+
+window.addBench('hyperapp', (el, getNextSearchResults) => {
+ const initialState = Object.assign({}, state, {
+ getNextSearchResults: getNextSearchResults(),
+ });
+
+ let currentDone;
+ const appActions = Object.assign({}, actions, {
+ onUpdate() {
+ currentDone();
+ }
+ });
+
+ const widget = app(initialState, appActions, view, el);
+
+ return (done) => {
+ widget.setSearchResults(getNextSearchResults());
+ currentDone = done;
+ };
+});
diff --git a/benchmarks/search-results/hyperapp/components/App.jsx b/benchmarks/search-results/hyperapp/components/App.jsx
new file mode 100644
index 0000000..8555be9
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/components/App.jsx
@@ -0,0 +1,50 @@
+const { h } = require('hyperapp');
+const Footer = require('./Footer');
+const SearchResultsItem = require('./SearchResultsItem');
+
+const state = {
+ searchResultsData: {
+ items: [],
+ },
+ purchased: {
+ // id-1: true,
+ // id-2: false
+ },
+};
+
+const actions = {
+ setSearchResults(searchResultsData) {
+ return { searchResultsData };
+ },
+ onUpdate() {
+ // for benchmark
+ },
+ purchased: {
+ buy(id) {
+ return { [id]: true };
+ }
+ }
+};
+
+function view(state, actions) {
+ return (
+
+
+ {state.searchResultsData.items.map((item) => (
+
+ ))}
+
+
+
+ );
+}
+
+module.exports = {
+ state,
+ actions,
+ view,
+};
diff --git a/benchmarks/search-results/hyperapp/components/Footer.jsx b/benchmarks/search-results/hyperapp/components/Footer.jsx
new file mode 100644
index 0000000..20b44f0
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/components/Footer.jsx
@@ -0,0 +1,483 @@
+const { h } = require('hyperapp');
+
+function Footer() {
+ return (
+
+ );
+}
+
+module.exports = Footer;
diff --git a/benchmarks/search-results/hyperapp/components/SearchResultsItem.jsx b/benchmarks/search-results/hyperapp/components/SearchResultsItem.jsx
new file mode 100644
index 0000000..56a5138
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/components/SearchResultsItem.jsx
@@ -0,0 +1,31 @@
+const { h } = require('hyperapp');
+
+function SearchResultsItem(props) {
+ const { item, purchased, buy } = props;
+ return (
+
+
{item.title}
+
+
{item.price}
+ {purchased ? (
+
Purchased!
+ ) : (
+
+ )}
+
+ );
+}
+
+module.exports = SearchResultsItem;
diff --git a/benchmarks/search-results/hyperapp/page.marko b/benchmarks/search-results/hyperapp/page.marko
new file mode 100644
index 0000000..e78fe00
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/page.marko
@@ -0,0 +1,23 @@
+import serverRender from './util/serverRender';
+import App from './components/App';
+
+
+ <@body>
+ $ var renderedHTML = serverRender(App, input.searchResults);
+ $!{renderedHTML}
+
+
+ @body>
+
diff --git a/benchmarks/search-results/hyperapp/rollup.config.js b/benchmarks/search-results/hyperapp/rollup.config.js
new file mode 100644
index 0000000..74d7082
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/rollup.config.js
@@ -0,0 +1,22 @@
+import commonjsPlugin from 'rollup-plugin-commonjs';
+import nodeResolvePlugin from 'rollup-plugin-node-resolve';
+import babelPlugin from 'rollup-plugin-babel';
+import path from 'path';
+
+process.env.NODE_ENV = 'production';
+
+export default {
+ input: path.resolve(__dirname, 'client.jsx'),
+ output: {
+ format: 'iife',
+ file: path.join(process.env.BUNDLES_DIR, 'hyperapp.js')
+ },
+ mame: 'app',
+ plugins: [
+ babelPlugin({
+ exclude: 'node_modules/**'
+ }),
+ nodeResolvePlugin(),
+ commonjsPlugin()
+ ],
+};
diff --git a/benchmarks/search-results/hyperapp/server.jsx b/benchmarks/search-results/hyperapp/server.jsx
new file mode 100644
index 0000000..ebc9806
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/server.jsx
@@ -0,0 +1,12 @@
+const { app } = require('hyperapp');
+const { renderToString } = require('hyperapp-render');
+const { state, actions, view } = require('./components/App');
+
+module.exports = function(getNextSearchResults) {
+ return function benchFn() {
+ const initialState = Object.assign({}, state, {
+ getNextSearchResults: getNextSearchResults(),
+ });
+ return renderToString(view(initialState, actions))
+ };
+};
diff --git a/benchmarks/search-results/hyperapp/util/serverRender.jsx b/benchmarks/search-results/hyperapp/util/serverRender.jsx
new file mode 100644
index 0000000..5bd9d9b
--- /dev/null
+++ b/benchmarks/search-results/hyperapp/util/serverRender.jsx
@@ -0,0 +1,6 @@
+const { renderToString } = require('hyperapp-render');
+
+module.exports = function infernoRender(App, colors) {
+ const state = Object.assign({}, App.state, { colors });
+ return renderToString(App.view(state, App.actions));
+};
diff --git a/package.json b/package.json
index 2aced70..cc18f58 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"bundle-marko": "node ./scripts/rollup.js marko",
"bundle-react": "node ./scripts/rollup.js react",
"bundle-preact": "node ./scripts/rollup.js preact",
+ "bundle-hyperapp": "node ./scripts/rollup.js hyperapp",
"bundle-vue": "npm run bundle-vue-server && node ./scripts/rollup.js vue",
"bundle-vue-server": "webpack --config benchmarks/color-picker/vue/webpack.config.js && webpack --config benchmarks/search-results/vue/webpack.config.js"
},
@@ -47,6 +48,8 @@
"express": "^4.11.2",
"format-number": "^3.0.0",
"google-closure-compiler-js": "^20170910.0.0",
+ "hyperapp": "^1.1.2",
+ "hyperapp-render": "^1.1.0",
"inferno": "^3.9.0",
"inferno-component": "^3.9.0",
"inferno-server": "^3.9.0",