Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step 1 — Switch from React to Preact #2

Open
wants to merge 1 commit into
base: 00-react
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.3.2",
"react-dom": "^16.3.2",
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting rid of react and react-dom

"preact": "^8.2.7",
"preact-compat": "^3.18.0",
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And replace it with preact and preact-compat

"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"start": "node scripts/start",
"build": "node scripts/build",
"test": "node scripts/test --env=jsdom",
"eject": "react-scripts eject",
"preanalyze": "npm run build",
"analyze": "source-map-explorer --html build/static/js/main.* > packages.html"
},
"devDependencies": {
"module-alias": "^2.0.6",
"preact-compat-enzyme": "^0.2.5",
"preact-render-to-json": "^3.6.6",
"preact-test-utils": "^0.1.3",
"source-map-explorer": "^1.5.0"
}
}
33 changes: 14 additions & 19 deletions packages.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="data:text/css;base64,LyogVmVuZG9yZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vcm1taC93ZWJ0cmVlbWFwL2Jsb2IvOWZhMGMwNjZhMTBlYTQ0MDJkOTYwYjBjNmMxYTQzMjg0NmFjN2ZjNC93ZWJ0cmVlbWFwLmNzcyAqLwoKLndlYnRyZWVtYXAtbm9kZSB7CiAgLyogUmVxdWlyZWQgYXR0cmlidXRlcy4gKi8KICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgb3ZlcmZsb3c6IGhpZGRlbjsgICAvKiBUbyBoaWRlIG92ZXJsb25nIGNhcHRpb25zLiAqLwogIGJhY2tncm91bmQ6IHdoaXRlOyAgLyogTm9kZXMgbXVzdCBiZSBvcGFxdWUgZm9yIHpJbmRleCBsYXllcmluZy4gKi8KICBib3JkZXI6IHNvbGlkIDFweCBibGFjazsgIC8qIENhbGN1bGF0aW9ucyBhc3N1bWUgMXB4IGJvcmRlci4gKi8KCiAgLyogT3B0aW9uYWw6IENTUyBhbmltYXRpb24uICovCiAgdHJhbnNpdGlvbjogdG9wICAgIDAuM3MsCiAgICAgICAgICAgICAgbGVmdCAgIDAuM3MsCiAgICAgICAgICAgICAgd2lkdGggIDAuM3MsCiAgICAgICAgICAgICAgaGVpZ2h0IDAuM3M7Cn0KCi8qIE9wdGlvbmFsOiBoaWdobGlnaHQgbm9kZXMgb24gbW91c2VvdmVyLiAqLwoud2VidHJlZW1hcC1ub2RlOmhvdmVyIHsKICBiYWNrZ3JvdW5kOiAjZWVlOwp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJhY2tncm91bmQgY29sb3JzIGRlcGVuZGluZyBvbiBzeW1ib2wuICovCi53ZWJ0cmVlbWFwLXN5bWJvbC1ic3MgewogIGJhY2tncm91bmQ6ICM2NkMyQTU7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLWRhdGEgewogIGJhY2tncm91bmQ6ICNGQzhENjI7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLXJlYWQtb25seV9kYXRhIHsKICBiYWNrZ3JvdW5kOiAjOERBMENCOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1jb2RlIHsKICBiYWNrZ3JvdW5kOiAjRTc4QUMzOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC13ZWFrX3N5bWJvbCB7CiAgYmFja2dyb3VuZDogI0E2RDg1NDsKfQoud2VidHJlZW1hcC1zeW1ib2wtYnNzLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjQjNFMkNEOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1kYXRhLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjRkRDREFDOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1yZWFkLW9ubHlfZGF0YS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0NCRDVFODsKfQoud2VidHJlZW1hcC1zeW1ib2wtY29kZS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0Y0Q0FFNDsKfQoud2VidHJlZW1hcC1zeW1ib2wtd2Vha19zeW1ib2wud2VidHJlZW1hcC1hZ2dyZWdhdGUgewogIGJhY2tncm91bmQ6ICNFNkY1Qzk7Cn0KCiNsZWdlbmQgPiAqIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNDQ0Owp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJvcmRlcnMgZGVwZW5kaW5nIG9uIGxldmVsLiAqLwoud2VidHJlZW1hcC1sZXZlbDAgewogIGJvcmRlcjogc29saWQgMXB4ICM0NDQ7Cn0KLndlYnRyZWVtYXAtbGV2ZWwxIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNjY2Owp9Ci53ZWJ0cmVlbWFwLWxldmVsMiB7CiAgYm9yZGVyOiBzb2xpZCAxcHggIzg4ODsKfQoud2VidHJlZW1hcC1sZXZlbDMgewogIGJvcmRlcjogc29saWQgMXB4ICNhYWE7Cn0KLndlYnRyZWVtYXAtbGV2ZWw0IHsKICBib3JkZXI6IHNvbGlkIDFweCAjY2NjOwp9CgovKiBPcHRpb25hbDogc3R5bGluZyBvbiBub2RlIGNhcHRpb25zLiAqLwoud2VidHJlZW1hcC1jYXB0aW9uIHsKICBmb250LWZhbWlseTogc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgcGFkZGluZzogMnB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKLyogT3B0aW9uYWw6IHN0eWxpbmcgb24gY2FwdGlvbnMgb24gbW91c2UgaG92ZXIuICovCi8qLndlYnRyZWVtYXAtbm9kZTpob3ZlciA+IC53ZWJ0cmVlbWFwLWNhcHRpb24gewogIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOwp9Ki8K">
<title>build/static/js/main.a3b22bcc.js - Source Map Explorer</title>
<title>build/static/js/main.d722544c.js - Source Map Explorer</title>

<style>
html, body {
Expand Down Expand Up @@ -43,31 +43,26 @@

<script>
var tree = {
"../static/js/main.a3b22bcc.js": 1936,
"../webpack/bootstrap ba60ac32d722a99c6e16": 449,
"../node_modules/object-assign/index.js": 923,
"../node_modules/react/index.js": 18,
"../static/js/main.d722544c.js": 2124,
"../webpack/bootstrap 37631ed09a0f3e7fb3b8": 449,
"../node_modules/preact-compat/dist/preact-compat.es.js": 9092,
"../node_modules/promise/lib/core.js": 1842,
"../node_modules/fbjs/lib/invariant.js": 374,
"../node_modules/fbjs/lib/emptyObject.js": 23,
"../node_modules/fbjs/lib/emptyFunction.js": 252,
"../node_modules/react-scripts/config/polyfills.js": 94,
"../node_modules/react-scripts/config/polyfills.js": 92,
"../node_modules/promise/lib/rejection-tracking.js": 1169,
"../node_modules/asap/browser-raw.js": 645,
"../node_modules/webpack/buildin/global.js": 146,
"../node_modules/promise/lib/es6-extensions.js": 1186,
"../node_modules/whatwg-fetch/fetch.js": 7254,
"../node_modules/object-assign/index.js": 923,
"index.js": 88,
"../node_modules/react/cjs/react.production.min.js": 5201,
"../node_modules/react-dom/index.js": 225,
"../node_modules/react-dom/cjs/react-dom.production.min.js": 98750,
"../node_modules/fbjs/lib/ExecutionEnvironment.js": 280,
"../node_modules/fbjs/lib/getActiveElement.js": 177,
"../node_modules/fbjs/lib/shallowEqual.js": 381,
"../node_modules/fbjs/lib/containsNode.js": 194,
"../node_modules/fbjs/lib/isTextNode.js": 67,
"../node_modules/fbjs/lib/isNode.js": 231,
"App.js": 401,
"../node_modules/process/browser.js": 1673,
"../node_modules/prop-types/index.js": 19,
"../node_modules/prop-types/factoryWithThrowingShims.js": 505,
"../node_modules/fbjs/lib/emptyFunction.js": 252,
"../node_modules/fbjs/lib/invariant.js": 374,
"../node_modules/prop-types/lib/ReactPropTypesSecret.js": 59,
"../node_modules/preact/dist/preact.esm.js": 8488,
"App.js": 482,
"logo.svg": 48,
"registerServiceWorker.js": 1269,
"<unmapped>": 42
Expand Down
10 changes: 10 additions & 0 deletions scripts/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node

process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';

const webpackPreact = require('./patch/webpackPreact');
const webpackConfig = require('react-scripts/config/webpack.config.prod');
webpackPreact(webpackConfig);

require('react-scripts/scripts/build');
6 changes: 6 additions & 0 deletions scripts/patch/webpackPreact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Hack the webpack config to load Preact instead of React
module.exports = webpackConfig =>
(webpackConfig.resolve.alias = Object.assign({}, webpackConfig.resolve.alias, {
react: 'preact-compat',
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whenever webpack is loading react, it will grab preact-compat instead

'react-dom': 'preact-compat'
}));
10 changes: 10 additions & 0 deletions scripts/start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env node

process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';

const webpackPreact = require('./patch/webpackPreact');
const webpackConfig = require('react-scripts/config/webpack.config.dev');
webpackPreact(webpackConfig);

require('react-scripts/scripts/start');
30 changes: 30 additions & 0 deletions scripts/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env node

process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';

// Load the create-react-app config.
const jestConfig = require('react-scripts/scripts/utils/createJestConfig');

// Map React's testing classes to Preact
const newJestConfig = function() {
const config = jestConfig.apply(this, arguments);
config.moduleNameMapper = Object.assign({}, config.moduleNameMapper, {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whenever jest tries to load or mock any react* modules, it will get the preact* equivalents.

'^react-dom/server$': '<rootDir>/node_modules/preact-render-to-string/dist/index.js',
'^react-dom/test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-dom$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js',
'^react-test-renderer/shallow$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-test-renderer$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react-addons-test-utils$': '<rootDir>/node_modules/preact-test-utils/lib/index.js',
'^react$': '<rootDir>/node_modules/preact-compat-enzyme/lib/index.js'
});
return config;
};

// HACK ALERT!
module.constructor._cache[
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HACK ALERT!

Preload Node's module cache with the hacked jest config we just made.

require.resolve('react-scripts/scripts/utils/createJestConfig')
].exports = newJestConfig;

// Run the build.
require('react-scripts/scripts/test');
8 changes: 8 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

// This is just a Thing
class Thing extends Component {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a Thing to show off shallow/deep rendering during testing.

render() {
return <div className="thing" />;
}
}

class App extends Component {
render() {
return (
Expand All @@ -13,6 +20,7 @@ class App extends Component {
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<Thing />
</div>
);
}
Expand Down
10 changes: 10 additions & 0 deletions src/App.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ it('renders without crashing', () => {
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

it('can render into snapshots', () => {
const tree = global.render(<App />);
expect(tree).toMatchSnapshot();
});

it('can shallow render into snapshots', () => {
const tree = global.shallowRender(<App />);
expect(tree).toMatchSnapshot();
});
65 changes: 65 additions & 0 deletions src/__snapshots__/App.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`can render into snapshots 1`] = `
<div
class="App"
>
<header
class="App-header"
>
<img
alt="logo"
class="App-logo"
src="logo.svg"
/>
<h1
class="App-title"
>
Welcome to React
</h1>
</header>
<p
class="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
<div
class="thing"
/>
</div>
`;

exports[`can shallow render into snapshots 1`] = `
<div
class="App"
>
<header
class="App-header"
>
<img
alt="logo"
class="App-logo"
src="logo.svg"
/>
<h1
class="App-title"
>
Welcome to React
</h1>
</header>
<p
class="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
<Thing />
</div>
`;
33 changes: 33 additions & 0 deletions src/setupTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import render, { shallowRender } from 'preact-render-to-json';

/**
* Remove __self and __source from the list of attributes/properties.
* babel-preset-react adds these for use with the React DevTools
*/
function removeDevAttributes(vnode) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

babel-preset-react adds __self and __source as props to every Component.

We need this small patch to make them go away and have reliable snapshot testing.

See preactjs/preact-render-to-string#43 (comment) for more info.

if (vnode) {
if (vnode.children) {
vnode.children.forEach(n => removeDevAttributes(n));
}
if (vnode.props) {
if (vnode.props.__source) {
delete vnode.props.__source;
}
if (vnode.props.__self) {
delete vnode.props.__self;
}
}
}
return vnode;
}

/**
* Render Preact JSX + Components to an HTML string.
*
* @param {VNode} vnode JSX VNode to render.
* @param {Object} [context={}] Optionally pass an initial context object through the render path.
* @param {Object} [options={}] Rendering options
*/
global.render = (vnode, context) => removeDevAttributes(render(vnode, context));

global.shallowRender = (vnode, context) => removeDevAttributes(shallowRender(vnode, context));
Loading