Skip to content

Commit 14bc486

Browse files
author
Daniel Spitzer
committed
Switch from React to Preact
1 parent 71a2fc7 commit 14bc486

11 files changed

+274
-47
lines changed

package.json

+10-5
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,24 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"react": "^16.3.2",
7-
"react-dom": "^16.3.2",
6+
"preact": "^8.2.7",
7+
"preact-compat": "^3.18.0",
88
"react-scripts": "1.1.4"
99
},
1010
"scripts": {
11-
"start": "react-scripts start",
12-
"build": "react-scripts build",
13-
"test": "react-scripts test --env=jsdom",
11+
"start": "node scripts/start",
12+
"build": "node scripts/build",
13+
"test": "node scripts/test --env=jsdom",
1414
"eject": "react-scripts eject",
1515
"preanalyze": "npm run build",
1616
"analyze": "source-map-explorer --html build/static/js/main.* > packages.html"
1717
},
1818
"devDependencies": {
19+
"module-alias": "^2.0.6",
20+
"preact-compat-enzyme": "^0.2.5",
21+
"preact-render-to-json": "^3.6.6",
22+
"preact-test-utils": "^0.1.3",
23+
"pretty-format": "^22.4.3",
1924
"source-map-explorer": "^1.5.0"
2025
}
2126
}

packages.html

+14-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<head>
33
<meta charset="UTF-8">
44
<link rel="stylesheet" href="data:text/css;base64,LyogVmVuZG9yZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vcm1taC93ZWJ0cmVlbWFwL2Jsb2IvOWZhMGMwNjZhMTBlYTQ0MDJkOTYwYjBjNmMxYTQzMjg0NmFjN2ZjNC93ZWJ0cmVlbWFwLmNzcyAqLwoKLndlYnRyZWVtYXAtbm9kZSB7CiAgLyogUmVxdWlyZWQgYXR0cmlidXRlcy4gKi8KICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgb3ZlcmZsb3c6IGhpZGRlbjsgICAvKiBUbyBoaWRlIG92ZXJsb25nIGNhcHRpb25zLiAqLwogIGJhY2tncm91bmQ6IHdoaXRlOyAgLyogTm9kZXMgbXVzdCBiZSBvcGFxdWUgZm9yIHpJbmRleCBsYXllcmluZy4gKi8KICBib3JkZXI6IHNvbGlkIDFweCBibGFjazsgIC8qIENhbGN1bGF0aW9ucyBhc3N1bWUgMXB4IGJvcmRlci4gKi8KCiAgLyogT3B0aW9uYWw6IENTUyBhbmltYXRpb24uICovCiAgdHJhbnNpdGlvbjogdG9wICAgIDAuM3MsCiAgICAgICAgICAgICAgbGVmdCAgIDAuM3MsCiAgICAgICAgICAgICAgd2lkdGggIDAuM3MsCiAgICAgICAgICAgICAgaGVpZ2h0IDAuM3M7Cn0KCi8qIE9wdGlvbmFsOiBoaWdobGlnaHQgbm9kZXMgb24gbW91c2VvdmVyLiAqLwoud2VidHJlZW1hcC1ub2RlOmhvdmVyIHsKICBiYWNrZ3JvdW5kOiAjZWVlOwp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJhY2tncm91bmQgY29sb3JzIGRlcGVuZGluZyBvbiBzeW1ib2wuICovCi53ZWJ0cmVlbWFwLXN5bWJvbC1ic3MgewogIGJhY2tncm91bmQ6ICM2NkMyQTU7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLWRhdGEgewogIGJhY2tncm91bmQ6ICNGQzhENjI7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLXJlYWQtb25seV9kYXRhIHsKICBiYWNrZ3JvdW5kOiAjOERBMENCOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1jb2RlIHsKICBiYWNrZ3JvdW5kOiAjRTc4QUMzOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC13ZWFrX3N5bWJvbCB7CiAgYmFja2dyb3VuZDogI0E2RDg1NDsKfQoud2VidHJlZW1hcC1zeW1ib2wtYnNzLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjQjNFMkNEOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1kYXRhLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjRkRDREFDOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1yZWFkLW9ubHlfZGF0YS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0NCRDVFODsKfQoud2VidHJlZW1hcC1zeW1ib2wtY29kZS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0Y0Q0FFNDsKfQoud2VidHJlZW1hcC1zeW1ib2wtd2Vha19zeW1ib2wud2VidHJlZW1hcC1hZ2dyZWdhdGUgewogIGJhY2tncm91bmQ6ICNFNkY1Qzk7Cn0KCiNsZWdlbmQgPiAqIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNDQ0Owp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJvcmRlcnMgZGVwZW5kaW5nIG9uIGxldmVsLiAqLwoud2VidHJlZW1hcC1sZXZlbDAgewogIGJvcmRlcjogc29saWQgMXB4ICM0NDQ7Cn0KLndlYnRyZWVtYXAtbGV2ZWwxIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNjY2Owp9Ci53ZWJ0cmVlbWFwLWxldmVsMiB7CiAgYm9yZGVyOiBzb2xpZCAxcHggIzg4ODsKfQoud2VidHJlZW1hcC1sZXZlbDMgewogIGJvcmRlcjogc29saWQgMXB4ICNhYWE7Cn0KLndlYnRyZWVtYXAtbGV2ZWw0IHsKICBib3JkZXI6IHNvbGlkIDFweCAjY2NjOwp9CgovKiBPcHRpb25hbDogc3R5bGluZyBvbiBub2RlIGNhcHRpb25zLiAqLwoud2VidHJlZW1hcC1jYXB0aW9uIHsKICBmb250LWZhbWlseTogc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgcGFkZGluZzogMnB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKLyogT3B0aW9uYWw6IHN0eWxpbmcgb24gY2FwdGlvbnMgb24gbW91c2UgaG92ZXIuICovCi8qLndlYnRyZWVtYXAtbm9kZTpob3ZlciA+IC53ZWJ0cmVlbWFwLWNhcHRpb24gewogIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOwp9Ki8K">
5-
<title>build/static/js/main.a3b22bcc.js - Source Map Explorer</title>
5+
<title>build/static/js/main.d722544c.js - Source Map Explorer</title>
66

77
<style>
88
html, body {
@@ -43,31 +43,26 @@
4343

4444
<script>
4545
var tree = {
46-
"../static/js/main.a3b22bcc.js": 1936,
47-
"../webpack/bootstrap ba60ac32d722a99c6e16": 449,
48-
"../node_modules/object-assign/index.js": 923,
49-
"../node_modules/react/index.js": 18,
46+
"../static/js/main.d722544c.js": 2124,
47+
"../webpack/bootstrap 37631ed09a0f3e7fb3b8": 449,
48+
"../node_modules/preact-compat/dist/preact-compat.es.js": 9092,
5049
"../node_modules/promise/lib/core.js": 1842,
51-
"../node_modules/fbjs/lib/invariant.js": 374,
52-
"../node_modules/fbjs/lib/emptyObject.js": 23,
53-
"../node_modules/fbjs/lib/emptyFunction.js": 252,
54-
"../node_modules/react-scripts/config/polyfills.js": 94,
50+
"../node_modules/react-scripts/config/polyfills.js": 92,
5551
"../node_modules/promise/lib/rejection-tracking.js": 1169,
5652
"../node_modules/asap/browser-raw.js": 645,
5753
"../node_modules/webpack/buildin/global.js": 146,
5854
"../node_modules/promise/lib/es6-extensions.js": 1186,
5955
"../node_modules/whatwg-fetch/fetch.js": 7254,
56+
"../node_modules/object-assign/index.js": 923,
6057
"index.js": 88,
61-
"../node_modules/react/cjs/react.production.min.js": 5201,
62-
"../node_modules/react-dom/index.js": 225,
63-
"../node_modules/react-dom/cjs/react-dom.production.min.js": 98750,
64-
"../node_modules/fbjs/lib/ExecutionEnvironment.js": 280,
65-
"../node_modules/fbjs/lib/getActiveElement.js": 177,
66-
"../node_modules/fbjs/lib/shallowEqual.js": 381,
67-
"../node_modules/fbjs/lib/containsNode.js": 194,
68-
"../node_modules/fbjs/lib/isTextNode.js": 67,
69-
"../node_modules/fbjs/lib/isNode.js": 231,
70-
"App.js": 401,
58+
"../node_modules/process/browser.js": 1673,
59+
"../node_modules/prop-types/index.js": 19,
60+
"../node_modules/prop-types/factoryWithThrowingShims.js": 505,
61+
"../node_modules/fbjs/lib/emptyFunction.js": 252,
62+
"../node_modules/fbjs/lib/invariant.js": 374,
63+
"../node_modules/prop-types/lib/ReactPropTypesSecret.js": 59,
64+
"../node_modules/preact/dist/preact.esm.js": 8488,
65+
"App.js": 482,
7166
"logo.svg": 48,
7267
"registerServiceWorker.js": 1269,
7368
"<unmapped>": 42

scripts/build.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env node
2+
3+
process.env.BABEL_ENV = 'production';
4+
process.env.NODE_ENV = 'production';
5+
6+
const webpackPreact = require('./patch/webpackPreact');
7+
const webpackConfig = require('react-scripts/config/webpack.config.prod');
8+
webpackPreact(webpackConfig);
9+
10+
require('react-scripts/scripts/build');

scripts/patch/webpackPreact.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Hack the webpack config to load Preact instead of React
2+
module.exports = webpackConfig =>
3+
(webpackConfig.resolve.alias = Object.assign({}, webpackConfig.resolve.alias, {
4+
react: 'preact-compat',
5+
'react-dom': 'preact-compat'
6+
}));

scripts/start.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env node
2+
3+
process.env.BABEL_ENV = 'development';
4+
process.env.NODE_ENV = 'development';
5+
6+
const webpackPreact = require('./patch/webpackPreact');
7+
const webpackConfig = require('react-scripts/config/webpack.config.dev');
8+
webpackPreact(webpackConfig);
9+
10+
require('react-scripts/scripts/start');

scripts/test.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env node
2+
3+
process.env.BABEL_ENV = 'test';
4+
process.env.NODE_ENV = 'test';
5+
6+
// Load the create-react-app config.
7+
const jestConfig = require('react-scripts/scripts/utils/createJestConfig');
8+
9+
// Map React's testing classes to Preact
10+
const newJestConfig = function() {
11+
const config = jestConfig.apply(this, arguments);
12+
config.moduleNameMapper = Object.assign({}, config.moduleNameMapper, {
13+
'^react-dom/server$': '<rootDir>/node_modules/preact-render-to-string/dist/index.js',
14+
'^react-dom/test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
15+
'^react-dom$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js',
16+
'^react-test-renderer/shallow$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
17+
'^react-test-renderer$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
18+
'^react-addons-test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
19+
'^react$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js'
20+
});
21+
return config;
22+
};
23+
24+
// HACK ALERT!
25+
module.constructor._cache[
26+
require.resolve('react-scripts/scripts/utils/createJestConfig')
27+
].exports = newJestConfig;
28+
29+
// Run the build.
30+
require('react-scripts/scripts/test');

src/App.js

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import React, { Component } from 'react';
22
import logo from './logo.svg';
33
import './App.css';
44

5+
// This is just a Thing
6+
class Thing extends Component {
7+
render() {
8+
return <div className="thing" />;
9+
}
10+
}
11+
512
class App extends Component {
613
render() {
714
return (
@@ -13,6 +20,7 @@ class App extends Component {
1320
<p className="App-intro">
1421
To get started, edit <code>src/App.js</code> and save to reload.
1522
</p>
23+
<Thing />
1624
</div>
1725
);
1826
}

src/App.test.js

+10
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ it('renders without crashing', () => {
77
ReactDOM.render(<App />, div);
88
ReactDOM.unmountComponentAtNode(div);
99
});
10+
11+
it('can render into snapshots', () => {
12+
const tree = global.render(<App />);
13+
expect(tree).toMatchSnapshot();
14+
});
15+
16+
it('can shallow render into snapshots', () => {
17+
const tree = global.shallowRender(<App />);
18+
expect(tree).toMatchSnapshot();
19+
});

src/__snapshots__/App.test.js.snap

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`can render into snapshots 1`] = `
4+
<div
5+
class="App"
6+
>
7+
<header
8+
class="App-header"
9+
>
10+
<img
11+
alt="logo"
12+
class="App-logo"
13+
src="logo.svg"
14+
/>
15+
<h1
16+
class="App-title"
17+
>
18+
Welcome to React
19+
</h1>
20+
</header>
21+
<p
22+
class="App-intro"
23+
>
24+
To get started, edit
25+
<code>
26+
src/App.js
27+
</code>
28+
and save to reload.
29+
</p>
30+
<div
31+
class="thing"
32+
/>
33+
</div>
34+
`;
35+
36+
exports[`can shallow render into snapshots 1`] = `
37+
<div
38+
class="App"
39+
>
40+
<header
41+
class="App-header"
42+
>
43+
<img
44+
alt="logo"
45+
class="App-logo"
46+
src="logo.svg"
47+
/>
48+
<h1
49+
class="App-title"
50+
>
51+
Welcome to React
52+
</h1>
53+
</header>
54+
<p
55+
class="App-intro"
56+
>
57+
To get started, edit
58+
<code>
59+
src/App.js
60+
</code>
61+
and save to reload.
62+
</p>
63+
<Thing />
64+
</div>
65+
`;

src/setupTests.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import render, { shallowRender } from 'preact-render-to-json';
2+
3+
/**
4+
* Remove __self and __source from the list of attributes/properties.
5+
* babel-preset-react adds these for use with the React DevTools
6+
*/
7+
function removeDevAttributes(vnode) {
8+
if (vnode) {
9+
if (vnode.children) {
10+
vnode.children.forEach(n => removeDevAttributes(n));
11+
}
12+
if (vnode.props) {
13+
if (vnode.props.__source) {
14+
delete vnode.props.__source;
15+
}
16+
if (vnode.props.__self) {
17+
delete vnode.props.__self;
18+
}
19+
}
20+
}
21+
return vnode;
22+
}
23+
24+
/**
25+
* Render Preact JSX + Components to an HTML string.
26+
*
27+
* @param {VNode} vnode JSX VNode to render.
28+
* @param {Object} [context={}] Optionally pass an initial context object through the render path.
29+
* @param {Object} [options={}] Rendering options
30+
*/
31+
global.render = (vnode, context) => removeDevAttributes(render(vnode, context));
32+
33+
global.shallowRender = (vnode, context) => removeDevAttributes(shallowRender(vnode, context));

0 commit comments

Comments
 (0)