npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rlyeh

v1.0.1

Published

Tweak React components in real time.

Downloads

2

Readme

Rlyeh

Build Status version MIT License

PRs Welcome

Watch on GitHub Star on GitHub

Tweak React components in real time ⚛️⚡️

  • Editing functional components preserves state
  • Works great with higher order components
  • Requires little configuration
  • Automatically disabled in production
  • Works with or without Babel (you can remove rlyeh/lib/babel-plugin from .babelrc and instead add rlyeh/lib/webpack to loaders)
  • Watch Dan Abramov's talk on Hot Reloading with Time Travel.

Install

npm install rlyeh

Getting started

  1. Add rlyeh/lib/babel to your .babelrc:
// .babelrc
{
  "plugins": ["rlyeh/lib/babel"]
}
  1. Enable Hot Module Replacement in Webpack

  2. Add rlyeh/lib/patch at the top of the entry section (except polyfills) of your Webpack config:

// webpack.config.js
module.exports = {
  entry: [
    'babel-polyfill',
    'rlyeh/lib/patch',
    './main.js'
  ]
}
  1. Wrap your application into <AppContainer>, all children of <AppContainer> will be reloaded when a change occurs:
// main.js
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'rlyeh'
import App from './containers/App'

const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <Component />
    </AppContainer>,
    document.getElementById('root'),
  )
}

render(App)

// Webpack Hot Module Replacement API
if (module.hot) {
  module.hot.accept('./containers/App', () => { render(App) })
}

Note: To make this work, you'll need to opt out of Babel transpiling ES2015 modules by changing the Babel ES2015 preset to be ["es2015", { "modules": false }]

Using Webpack loader instead of Babel plugin

You may not use Babel in your project, Rlyeh provides a Webpack loader with limited support. If you want to use it, you can add it in your Webpack config. If you use Babel, you don't need to add this loader.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: ['rlyeh/lib/webpack']
      }
    ]
  }
}

Migrating from create-react-app

  • Run npm run eject

  • Install Rlyeh (npm install --save-dev rlyeh)

  • In config/webpack.config.dev.js:

    1. Add 'rlyeh/lib/patch' to entry array (anywhere before paths.appIndexJs). It should now look like (excluding comments):
      entry: [
         'rlyeh/lib/patch',
         require.resolve('react-dev-utils/webpackHotDevClient'),
         require.resolve('./polyfills'),
         paths.appIndexJs
      ]
    1. Add 'rlyeh/lib/babel' to Babel loader configuration. The loader should now look like:
      {
         test: /\.(js|jsx)$/,
         include: paths.appSrc,
         loader: 'babel',
         query: {
           cacheDirectory: findCacheDir({
             name: 'react-scripts'
           }),
           plugins: [
             'rlyeh/lib/babel'
           ]
         }
      }
  • Add AppContainer to src/index.js (see step 4 of Getting Started).

TypeScript

When using TypeScript, Babel is not required, so your config should look like (demo):

{
  test: /\.tsx?$/,
  loaders: ['rlyeh/lib/webpack', 'ts-loader'] // (or awesome-typescript-loader)
}

Source Maps

If you use devtool: 'source-map' (or its equivalent), source maps will be emitted to hide hot reloading code.

Source maps slow down your project. Use devtool: 'eval' for best build performance.

Hot reloading code is just one line in the beginning and one line in the end of each module so you might not need source maps at all.

React Native

React Native supports hot reloading natively as of version 0.22.

Adding a custom error reporter

The previously used Redbox for Rlyeh has known limitations due to sourcemaps and it's no longer a default catcher. Errors are great to clearly see rendering issues, and avoiding an uncaught error from breaking your app. But there are some advantages to a thrown error in the console too, like filename resolution via sourcemaps, and click-to-open. To get the Redbox back, and have the best of both worlds, modify your app entry point as follows:

import Redbox from 'redbox-react';

const CustomErrorReporter = ({ error }) => <Redbox error={ error } />;

CustomErrorReporter.propTypes = {
  error: React.PropTypes.instanceOf(Error).isRequired
};

render((
  <AppContainer errorReporter={ CustomErrorReporter }>
    <AppRoot />
  </AppContainer>
), document.getElementById('react-root'));

You'll also need to npm install --save-dev redbox-react.

Starter Kit

Provided by collaborators:

Provided by community:

Known limitations

Components not replaced

  • Rlyeh can't replace any Component, only registered ones.
    • when using webpack loader - only module exports are registered.
    • when using babel plugin - only top level variables are registered.
    • when Rlyeh can't replace Component, an error message will be displayed.

Code Splitting

If you want to use Webpack code splitting via require.ensure, you'll need to add an additional module.hot.accept callback within the require.ensure block, like this:

require.ensure([], (require) => {
  if (module.hot) {
    module.hot.accept('../components/App', () => {
      loadComponent(require('../components/App').default);
    })
  }
  loadComponent(require('../components/App').default);
});

Note that if you're using React Router (pre-4.0), this will only work with getChildRoutes, but not getComponent, since getComponent's callback will only load a component once.

Also, if you're using the Webpack 2 beta, you can use System.import without extra module.hot.accept calls, although there are still a few issues with it.

Checking Element types

Because Rlyeh creates proxied versions of your components, comparing reference types of elements won't work:

const element = <Component />;
console.log(element.type === Component); // false

One workaround is to create an element (that will have the type of the proxied component):

const ComponentType = (<Component />).type;
const element = <Component />;
console.log(element.type === ComponentType); // true

You can also set a property on the component class:

const Widget = () => <div>hi</div>;
Widget.isWidgetType = true;
console.log(<Widget />.type.isWidgetType); // true

Reassigning Components

Rlyeh will only try to reload the original component reference, so if you reassign it to another variable like this:

let App = () => (<div>hello</div>);
App = connect()(App);
export default App;

Rlyeh won't reload it. Instead, you'll need to define it once:

const App = () => (<div>hello</div>);
export default connect()(App);

Decorators

Components that are decorated (using something like @autobind) currently do not retain state when being hot-reloaded. (see #279)

Troubleshooting

If it doesn't work, in 99% cases it's a configuration issue. A missing option, a wrong path or port. Webpack is very strict about configuration, and the best way to find out what's wrong is to compare your project to an already working setup, such as React Hot Boilerplate, bit by bit.

If something doesn't work, in 99% cases it's an issue with your code - Component doesn't got registered, due to HOC or Decorator around it, which making it invisible to Babel plugin, or Webpack loader.

We're also gathering Troubleshooting Recipes so send a PR if you have a lesson to share!

Patrons

License

MIT