React compatibility layer for Preact

preact-compat

This module is a compatibility layer that makes React-based modules work with Preact, without any code changes.

It provides the same exports as react and react-dom, meaning you can use your build tool of choice to drop it in where React is being depended on.

Interested? Here's an example project that uses preact-compat to work with an existing React library unmodified,
achieving more than 95% reduction in size:

preact-compat-example


Why?

... or really, "why [preact]"?

React is a great library and a great concept, and has a large community of module authors creating high-quality components.
However, these components are tightly coupled to React through the use of generic package imports ([example][1]).

[Preact] is a tiny (3kb) implementation of the core value of React, and maintains a nearly identical API.
With a shim like this in place, it is possible to use other React-like libraries like Preact, without forking modules just to change their imports.

There are better long-term ways to solve the coupling issue, like using factory functions that accept named generic methods (not just React DI),
as [suggested by Eric Elliot][2]. However, since the React community has already authored so many modules in a more explicitly coupled manner, it's worth
having a simple short-term solution for those who would like to liberate themselves from library lock-in.


Installation

You need to install preact-compat first through npm:

npm i --save preact-compat

NOTE: You need to have preact already installed, if you don't, install it like so:

npm i --save preact

Usage with Webpack

Using preact-compat with Webpack is easy.

All you have to do is add an alias for react and react-dom:

{
    // ...
    resolve: {
        alias: {
            'react': 'preact-compat',
            'react-dom': 'preact-compat',
            // Not necessary unless you consume a module using `createClass`
            'create-react-class': 'preact-compat/lib/create-react-class',
            // Not necessary unless you consume a module requiring `react-dom-factories`
            'react-dom-factories': 'preact-compat/lib/react-dom-factories'
        }
    }
    // ...
}

Usage with Browserify

Using preact-compat with Browserify is as simple as installing and configuring aliasify.

First, install it: npm install --save-dev aliasify

... then in your package.json, configure aliasify to alias react and react-dom:

{
    // ...
    "aliasify": {
        "aliases": {
            "react": "preact-compat",
            "react-dom": "preact-compat",
            // Not necessary unless you consume a module using `createClass`
            "create-react-class": "preact-compat/lib/create-react-class",
            // Not necessary unless you consume a module requiring `react-dom-factories`
            "react-dom-factories": "preact-compat/lib/react-dom-factories"
        }
    }
    // ...
}

Usage with Babel

Using preact-compat with Babel is easy.

Install the babel plugin for aliasing: npm install --save-dev babel-plugin-module-resolver

All you have to do is tell babel to process jsx with 'h' and add an alias for react and react-dom in your .babelrc:

{
    // ...
    "plugins": [
        ["module-resolver", {
        "root": ["."],
        "alias": {
            "react": "preact-compat",
            "react-dom": "preact-compat",
            // Not necessary unless you consume a module using `createClass`
            "create-react-class": "preact-compat/lib/create-react-class",
            // Not necessary unless you consume a module requiring `react-dom-factories`
            "react-dom-factories" "preact-compat/lib/react-dom-factories"
        }
        }]
    ],
    "presets": [
        "react"
    ]
    // ...
}

Usage with Brunch

Using preact-compat with Brunch requires no extra plugins.

In your brunch-config.js you can export an npm object to configure aliases:

// ...
exports.npm = {
  enabled: true,
  aliases: {
    'react': 'preact-compat',
    'react-dom': 'preact-compat'
  }
}
// ...

Once Aliased

With the above Webpack or Browserify aliases in place, existing React modules should work nicely:

import React, { Component } from 'react';
import { render } from 'react-dom';

class Foo extends Component {
    propTypes = {
        a: React.PropTypes.string.isRequired
    };
    render() {
        let { a, b, children } = this.props;
        return <div {...{a,b}}>{ children }</div>;
    }
}

render((
    <Foo a="a">test</Foo>
), document.body);

Use Without Webpack/Browserify

preact-compat and its single dependency prop-types are both published as UMD modules as of preact-compat version 0.6. This means you can use them via a <script> tag without issue:

<script src="//unpkg.com/preact"></script>
<script src="//unpkg.com/prop-types/prop-types.min.js"></script>
<script src="//unpkg.com/preact-compat"></script>
<script>
    var React = preactCompat,
        ReactDOM = preactCompat;
    ReactDOM.render(<h1>Hello!</h1>, document.body);
</script>

You can see the above in action with this JSFiddle Example.


PropTypes

preact-compat adds support for validating PropTypes out of the box. This can be disabled the same way it is when using React, by defining a global process.env.NODE_ENV='production'. PropType errors should work the same as in React - the prop-types module used here is published by the React team to replace PropTypes in React.

GitHub