• Stars
    star
    16,596
  • Rank 1,586 (Top 0.04 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

⏳ A higher order component for loading components with promises.

React Loadable

A higher order component for loading components with dynamic imports.

Install

yarn add react-loadable

Example

import Loadable from 'react-loadable';
import Loading from './my-loading-component';

const LoadableComponent = Loadable({
  loader: () => import('./my-component'),
  loading: Loading,
});

export default class App extends React.Component {
  render() {
    return <LoadableComponent/>;
  }
}

Happy Customers:

Users

If your company or project is using React Loadable, please open a PR and add yourself to this list (in alphabetical order please)

Also See:

  • react-loadable-visibility - Building on top of and keeping the same API as react-loadable, this library enables you to load content that is visible on the screen.

  • react-loadable-ssr-addon - Server Side Render add-on for react-loadable. Discover & load automatically dynamically all files dependencies, e.g. splitted chunks, css, etc.



GUIDE

Guide

So you've got your React app, you're bundling it with Webpack, and things are going smooth. But then one day you notice your app's bundle is getting so big that it's slowing things down.

It's time to start code-splitting your app!

A single giant bundle vs multiple smaller bundles

Code-splitting is the process of taking one large bundle containing your entire app, and splitting them up into multiple smaller bundles which contain separate parts of your app.

This might seem difficult to do, but tools like Webpack have this built in, and React Loadable is designed to make it super simple.

Route-based splitting vs. Component-based splitting

A common piece of advice you will see is to break your app into separate routes and load each one asynchronously. This seems to work well enough for many apps– as a user, clicking a link and waiting for a page to load is a familiar experience on the web.

But we can do better than that.

Using most routing tools for React, a route is simply a component. There's nothing particularly special about them (Sorry Ryan and Michael– you're what's special). So what if we optimized for splitting around components instead of routes? What would that get us?

Route vs. component centric code splitting

As it turns out: Quite a lot. There are many more places than just routes where you can pretty easily split apart your app. Modals, tabs, and many more UI components hide content until the user has done something to reveal it.

Example: Maybe your app has a map buried inside of a tab component. Why would you load a massive mapping library for the parent route every time when the user may never go to that tab?

Not to mention all the places where you can defer loading content until higher priority content is finished loading. That component at the bottom of your page which loads a bunch of libraries: Why should that be loaded at the same time as the content at the top?

And because routes are just components, we can still easily code-split at the route level.

Introducing new code-splitting points in your app should be so easy that you don't think twice about it. It should be a matter of changing a few lines of code and everything else should be automated.

Introducing React Loadable

React Loadable is a small library that makes component-centric code splitting incredibly easy in React.

Loadable is a higher-order component (a function that creates a component) which lets you dynamically load any module before rendering it into your app.

Let's imagine two components, one that imports and renders another.

import Bar from './components/Bar';

class Foo extends React.Component {
  render() {
    return <Bar/>;
  }
}

Right now we're depending on Bar being imported synchronously via import, but we don't need it until we go to render it. So why don't we just defer that?

Using a dynamic import (a tc39 proposal currently at Stage 3) we can modify our component to load Bar asynchronously.

class MyComponent extends React.Component {
  state = {
    Bar: null
  };

  componentWillMount() {
    import('./components/Bar').then(Bar => {
      this.setState({ Bar: Bar.default });
    });
  }

  render() {
    let {Bar} = this.state;
    if (!Bar) {
      return <div>Loading...</div>;
    } else {
      return <Bar/>;
    };
  }
}

But that's a whole bunch of work, and it doesn't even handle a bunch of cases. What about when import() fails? What about server-side rendering?

Instead you can use Loadable to abstract away the problem.

import Loadable from 'react-loadable';

const LoadableBar = Loadable({
  loader: () => import('./components/Bar'),
  loading() {
    return <div>Loading...</div>
  }
});

class MyComponent extends React.Component {
  render() {
    return <LoadableBar/>;
  }
}

Automatic code-splitting on import()

When you use import() with Webpack 2+, it will automatically code-split for you with no additional configuration.

This means that you can easily experiment with new code splitting points just by switching to import() and using React Loadable. Figure out what performs best for your app.

Creating a great "Loading..." Component

Rendering a static "Loading..." doesn't communicate enough to the user. You also need to think about error states, timeouts, and making it a nice experience.

function Loading() {
  return <div>Loading...</div>;
}

Loadable({
  loader: () => import('./WillFailToLoad'), // oh no!
  loading: Loading,
});

To make this all nice, your loading component receives a couple different props.

Loading error states

When your loader fails, your loading component will receive an error prop which will be an Error object (otherwise it will be null).

function Loading(props) {
  if (props.error) {
    return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
  } else {
    return <div>Loading...</div>;
  }
}

Avoiding Flash Of Loading Component

Sometimes components load really quickly (<200ms) and the loading screen only quickly flashes on the screen.

A number of user studies have proven that this causes users to perceive things taking longer than they really have. If you don't show anything, users perceive it as being faster.

So your loading component will also get a pastDelay prop which will only be true once the component has taken longer to load than a set delay.

function Loading(props) {
  if (props.error) {
    return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
  } else if (props.pastDelay) {
    return <div>Loading...</div>;
  } else {
    return null;
  }
}

This delay defaults to 200ms but you can also customize the delay in Loadable.

Loadable({
  loader: () => import('./components/Bar'),
  loading: Loading,
  delay: 300, // 0.3 seconds
});

Timing out when the loader is taking too long

Sometimes network connections suck and never resolve or fail, they just hang there forever. This sucks for the user because they won't know if it should always take this long, or if they should try refreshing.

The loading component will receive a timedOut prop which will be set to true when the loader has timed out.

function Loading(props) {
  if (props.error) {
    return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
  } else if (props.timedOut) {
    return <div>Taking a long time... <button onClick={ props.retry }>Retry</button></div>;
  } else if (props.pastDelay) {
    return <div>Loading...</div>;
  } else {
    return null;
  }
}

However, this feature is disabled by default. To turn it on, you can pass a timeout option to Loadable.

Loadable({
  loader: () => import('./components/Bar'),
  loading: Loading,
  timeout: 10000, // 10 seconds
});

Customizing rendering

By default Loadable will render the default export of the returned module. If you want to customize this behavior you can use the render option.

Loadable({
  loader: () => import('./my-component'),
  render(loaded, props) {
    let Component = loaded.namedExport;
    return <Component {...props}/>;
  }
});

Loading multiple resources

Technically you can do whatever you want within loader() as long as it returns a promise and you're able to render something. But writing it out can be a bit annoying.

To make it easier to load multiple resources in parallel, you can use Loadable.Map.

Loadable.Map({
  loader: {
    Bar: () => import('./Bar'),
    i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
  },
  render(loaded, props) {
    let Bar = loaded.Bar.default;
    let i18n = loaded.i18n;
    return <Bar {...props} i18n={i18n}/>;
  },
});

When using Loadable.Map the render() method is required. It will be passed a loaded param which will be an object matching the shape of your loader.

Preloading

As an optimization, you can also decide to preload a component before it gets rendered.

For example, if you need to load a new component when a button gets pressed, you could start preloading the component when the user hovers over the button.

The component created by Loadable exposes a static preload method which does exactly this.

const LoadableBar = Loadable({
  loader: () => import('./Bar'),
  loading: Loading,
});

class MyComponent extends React.Component {
  state = { showBar: false };

  onClick = () => {
    this.setState({ showBar: true });
  };

  onMouseOver = () => {
    LoadableBar.preload();
  };

  render() {
    return (
      <div>
        <button
          onClick={this.onClick}
          onMouseOver={this.onMouseOver}>
          Show Bar
        </button>
        {this.state.showBar && <LoadableBar/>}
      </div>
    )
  }
}



SERVER SIDE RENDERING

Server-Side Rendering

When you go to render all these dynamically loaded components, what you'll get is a whole bunch of loading screens.

This really sucks, but the good news is that React Loadable is designed to make server-side rendering work as if nothing is being loaded dynamically.

Here's our starting server using Express.

import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './components/App';

const app = express();

app.get('/', (req, res) => {
  res.send(`
    <!doctype html>
    <html lang="en">
      <head>...</head>
      <body>
        <div id="app">${ReactDOMServer.renderToString(<App/>)}</div>
        <script src="/dist/main.js"></script>
      </body>
    </html>
  `);
});

app.listen(3000, () => {
  console.log('Running on http://localhost:3000/');
});

Preloading all your loadable components on the server

The first step to rendering the correct content from the server is to make sure that all of your loadable components are already loaded when you go to render them.

To do this, you can use the Loadable.preloadAll method. It returns a promise that will resolve when all your loadable components are ready.

Loadable.preloadAll().then(() => {
  app.listen(3000, () => {
    console.log('Running on http://localhost:3000/');
  });
});

Picking up a server-side rendered app on the client

This is where things get a little bit tricky. So let's prepare ourselves little bit.

In order for us to pick up what was rendered from the server we need to have all the same code that was used to render on the server.

To do this, we first need our loadable components telling us which modules they are rendering.

Declaring which modules are being loaded

There are two options in Loadable and Loadable.Map which are used to tell us which modules our component is trying to load: opts.modules and opts.webpack.

Loadable({
  loader: () => import('./Bar'),
  modules: ['./Bar'],
  webpack: () => [require.resolveWeak('./Bar')],
});

But don't worry too much about these options. React Loadable includes a Babel plugin to add them for you.

Just add the react-loadable/babel plugin to your Babel config:

{
  "plugins": [
    "react-loadable/babel"
  ]
}

Now these options will automatically be provided.

For typescript you can use react-loadable-ts-transformer which is a ts analog of react-loadable/babel plugin.

Finding out which dynamic modules were rendered

Next we need to find out which modules were actually rendered when a request comes in.

For this, there is Loadable.Capture component which can be used to collect all the modules that were rendered.

import Loadable from 'react-loadable';

app.get('/', (req, res) => {
  let modules = [];

  let html = ReactDOMServer.renderToString(
    <Loadable.Capture report={moduleName => modules.push(moduleName)}>
      <App/>
    </Loadable.Capture>
  );

  console.log(modules);

  res.send(`...${html}...`);
});

Mapping loaded modules to bundles

In order to make sure that the client loads all the modules that were rendered server-side, we'll need to map them to the bundles that Webpack created.

This comes in two parts.

First we need Webpack to tell us which bundles each module lives inside. For this there is the React Loadable Webpack plugin.

Import the ReactLoadablePlugin from react-loadable/webpack and include it in your webpack config. Pass it a filename for where to store the JSON data about our bundles.

// webpack.config.js
import { ReactLoadablePlugin } from 'react-loadable/webpack';

export default {
  plugins: [
    new ReactLoadablePlugin({
      filename: './dist/react-loadable.json',
    }),
  ],
};

Then we'll go back to our server and use this data to convert our modules to bundles.

To convert from modules to bundles, import the getBundles method from react-loadable/webpack and the data from Webpack.

import Loadable from 'react-loadable';
import { getBundles } from 'react-loadable/webpack'
import stats from './dist/react-loadable.json';

app.get('/', (req, res) => {
  let modules = [];

  let html = ReactDOMServer.renderToString(
    <Loadable.Capture report={moduleName => modules.push(moduleName)}>
      <App/>
    </Loadable.Capture>
  );

  let bundles = getBundles(stats, modules);

  // ...
});

We can then render these bundles into <script> tags in our HTML.

It is important that the bundles are included before the main bundle, so that they can be loaded by the browser prior to the app rendering.

However, as the Webpack manifest (including the logic for parsing bundles) lives in the main bundle, it will need to be extracted into its own chunk.

This is easy to do with the CommonsChunkPlugin

// webpack.config.js
export default {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    })
  ]
}

Notice: As of Webpack 4 the CommonsChunkPlugin has been removed and the manifest doesn't need to be extracted anymore.

let bundles = getBundles(stats, modules);

res.send(`
  <!doctype html>
  <html lang="en">
    <head>...</head>
    <body>
      <div id="app">${html}</div>
      <script src="/dist/manifest.js"></script>
      <script src="/dist/main.js"></script>
      ${bundles.map(bundle => {
        return `<script src="/dist/${bundle.file}"></script>`
        // alternatively if you are using publicPath option in webpack config
        // you can use the publicPath value from bundle, e.g:
        // return `<script src="${bundle.publicPath}"></script>`
      }).join('\n')}
      <script>window.main();</script>
    </body>
  </html>
`);

Preloading ready loadable components on the client

We can use the Loadable.preloadReady() method on the client to preload the loadable components that were included on the page.

Like Loadable.preloadAll(), it returns a promise, which on resolution means that we can hydrate our app.

// src/entry.js
import React from 'react';
import ReactDOM from 'react-dom';
import Loadable from 'react-loadable';
import App from './components/App';

window.main = () => {
  Loadable.preloadReady().then(() => {
    ReactDOM.hydrate(<App/>, document.getElementById('app'));
  });
};

Now server-side rendering should work perfectly!



API DOCS

API Docs

Loadable

A higher-order component for dynamically loading a module before rendering it, a loading component is rendered while the module is unavailable.

const LoadableComponent = Loadable({
  loader: () => import('./Bar'),
  loading: Loading,
  delay: 200,
  timeout: 10000,
});

This returns a LoadableComponent.

Loadable.Map

A higher-order component that allows you to load multiple resources in parallel.

Loadable.Map's opts.loader accepts an object of functions, and needs a opts.render method.

Loadable.Map({
  loader: {
    Bar: () => import('./Bar'),
    i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
  },
  render(loaded, props) {
    let Bar = loaded.Bar.default;
    let i18n = loaded.i18n;
    return <Bar {...props} i18n={i18n}/>;
  }
});

When using Loadable.Map the render() method's loaded param will be an object with the same shape as your loader.

Loadable and Loadable.Map Options

opts.loader

A function returning a promise that loads your module.

Loadable({
  loader: () => import('./Bar'),
});

When using with Loadable.Map this accepts an object of these types of functions.

Loadable.Map({
  loader: {
    Bar: () => import('./Bar'),
    i18n: () => fetch('./i18n/bar.json').then(res => res.json()),
  },
});

When using with Loadable.Map you'll also need to pass a opts.render function.

opts.loading

A LoadingComponent that renders while a module is loading or when it errors.

Loadable({
  loading: LoadingComponent,
});

This option is required, if you don't want to render anything, return null.

Loadable({
  loading: () => null,
});

opts.delay

Time to wait (in milliseconds) before passing props.pastDelay to your loading component. This defaults to 200.

Loadable({
  delay: 200
});

Read more about delays.

opts.timeout

Time to wait (in milliseconds) before passing props.timedOut to your loading component. This is turned off by default.

Loadable({
  timeout: 10000
});

Read more about timeouts.

opts.render

A function to customize the rendering of loaded modules.

Receives loaded which is the resolved value of opts.loader and props which are the props passed to the LoadableComponent.

Loadable({
  render(loaded, props) {
    let Component = loaded.default;
    return <Component {...props}/>;
  }
});

opts.webpack

An optional function which returns an array of Webpack module ids which you can get with require.resolveWeak.

Loadable({
  loader: () => import('./Foo'),
  webpack: () => [require.resolveWeak('./Foo')],
});

This option can be automated with the Babel Plugin.

opts.modules

An optional array with module paths for your imports.

Loadable({
  loader: () => import('./my-component'),
  modules: ['./my-component'],
});

This option can be automated with the Babel Plugin.

LoadableComponent

This is the component returned by Loadable and Loadable.Map.

const LoadableComponent = Loadable({
  // ...
});

Props passed to this component will be passed straight through to the dynamically loaded component via opts.render.

LoadableComponent.preload()

This is a static method on LoadableComponent which can be used to load the component ahead of time.

const LoadableComponent = Loadable({...});

LoadableComponent.preload();

This returns a promise, but you should avoid waiting for that promise to resolve to update your UI. In most cases it creates a bad user experience.

Read more about preloading.

LoadingComponent

This is the component you pass to opts.loading.

function LoadingComponent(props) {
  if (props.error) {
    // When the loader has errored
    return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
  } else if (props.timedOut) {
    // When the loader has taken longer than the timeout
    return <div>Taking a long time... <button onClick={ props.retry }>Retry</button></div>;
  } else if (props.pastDelay) {
    // When the loader has taken longer than the delay
    return <div>Loading...</div>;
  } else {
    // When the loader has just started
    return null;
  }
}

Loadable({
  loading: LoadingComponent,
});

Read more about loading components

props.error

An Error object passed to LoadingComponent when the loader has failed. When there is no error, null is passed.

function LoadingComponent(props) {
  if (props.error) {
    return <div>Error!</div>;
  } else {
    return <div>Loading...</div>;
  }
}

Read more about errors.

props.retry

A function prop passed to LoadingComponent when the loader has failed, used to retry loading the component.

function LoadingComponent(props) {
  if (props.error) {
    return <div>Error! <button onClick={ props.retry }>Retry</button></div>;
  } else {
    return <div>Loading...</div>;
  }
}

Read more about errors.

props.timedOut

A boolean prop passed to LoadingComponent after a set timeout.

function LoadingComponent(props) {
  if (props.timedOut) {
    return <div>Taking a long time...</div>;
  } else {
    return <div>Loading...</div>;
  }
}

Read more about timeouts.

props.pastDelay

A boolean prop passed to LoadingComponent after a set delay.

function LoadingComponent(props) {
  if (props.pastDelay) {
    return <div>Loading...</div>;
  } else {
    return null;
  }
}

Read more about delays.

Loadable.preloadAll()

This will call all of the LoadableComponent.preload methods recursively until they are all resolved. Allowing you to preload all of your dynamic modules in environments like the server.

Loadable.preloadAll().then(() => {
  app.listen(3000, () => {
    console.log('Running on http://localhost:3000/');
  });
});

It's important to note that this requires that you declare all of your loadable components when modules are initialized rather than when your app is being rendered.

Good:

// During module initialization...
const LoadableComponent = Loadable({...});

class MyComponent extends React.Component {
  componentDidMount() {
    // ...
  }
}

Bad:

// ...

class MyComponent extends React.Component {
  componentDidMount() {
    // During app render...
    const LoadableComponent = Loadable({...});
  }
}

Note: Loadable.preloadAll() will not work if you have more than one copy of react-loadable in your app.

Read more about preloading on the server.

Loadable.preloadReady()

Check for modules that are already loaded in the browser and call the matching LoadableComponent.preload methods.

Loadable.preloadReady().then(() => {
  ReactDOM.hydrate(<App/>, document.getElementById('app'));
});

Read more about preloading on the client.

Loadable.Capture

A component for reporting which modules were rendered.

Accepts a report prop which is called for every moduleName that is rendered via React Loadable.

let modules = [];

let html = ReactDOMServer.renderToString(
  <Loadable.Capture report={moduleName => modules.push(moduleName)}>
    <App/>
  </Loadable.Capture>
);

console.log(modules);

Read more about capturing rendered modules.

Babel Plugin

Providing opts.webpack and opts.modules for every loadable component is a lot of manual work to remember to do.

Instead you can add the Babel plugin to your config and it will automate it for you:

{
  "plugins": ["react-loadable/babel"]
}

Input

import Loadable from 'react-loadable';

const LoadableMyComponent = Loadable({
  loader: () => import('./MyComponent'),
});

const LoadableComponents = Loadable.Map({
  loader: {
    One: () => import('./One'),
    Two: () => import('./Two'),
  },
});

Output

import Loadable from 'react-loadable';
import path from 'path';

const LoadableMyComponent = Loadable({
  loader: () => import('./MyComponent'),
  webpack: () => [require.resolveWeak('./MyComponent')],
  modules: [path.join(__dirname, './MyComponent')],
});

const LoadableComponents = Loadable.Map({
  loader: {
    One: () => import('./One'),
    Two: () => import('./Two'),
  },
  webpack: () => [require.resolveWeak('./One'), require.resolveWeak('./Two')],
  modules: [path.join(__dirname, './One'), path.join(__dirname, './Two')],
});

Read more about declaring modules.

Webpack Plugin

In order to send the right bundles down when rendering server-side, you'll need the React Loadable Webpack plugin  to provide you with a mapping of modules to bundles.

// webpack.config.js
import { ReactLoadablePlugin } from 'react-loadable/webpack';

export default {
  plugins: [
    new ReactLoadablePlugin({
      filename: './dist/react-loadable.json',
    }),
  ],
};

This will create a file (opts.filename) which you can import to map modules to bundles.

Read more about mapping modules to bundles.

getBundles

A method exported by react-loadable/webpack for converting modules to bundles.

import { getBundles } from 'react-loadable/webpack';

let bundles = getBundles(stats, modules);

Read more about mapping modules to bundles.



FAQ

FAQ

How do I avoid repetition?

Specifying the same loading component or delay every time you use Loadable() gets repetitive fast. Instead you can wrap Loadable with your own Higher-Order Component (HOC) to set default options.

import Loadable from 'react-loadable';
import Loading from './my-loading-component';

export default function MyLoadable(opts) {
  return Loadable(Object.assign({
    loading: Loading,
    delay: 200,
    timeout: 10000,
  }, opts));
};

Then you can just specify a loader when you go to use it.

import MyLoadable from './MyLoadable';

const LoadableMyComponent = MyLoadable({
  loader: () => import('./MyComponent'),
});

export default class App extends React.Component {
  render() {
    return <LoadableMyComponent/>;
  }
}

Unfortunately at the moment using wrapped Loadable breaks react-loadable/babel so in such case you have to add required properties (modules, webpack) manually.

import MyLoadable from './MyLoadable';

const LoadableMyComponent = MyLoadable({
  loader: () => import('./MyComponent'),
  modules: ['./MyComponent'],
  webpack: () => [require.resolveWeak('./MyComponent')],
});

export default class App extends React.Component {
  render() {
    return <LoadableMyComponent/>;
  }
}

How do I handle other styles .css or sourcemaps .map with server-side rendering?

When you call getBundles, it may return file types other than JavaScript depending on your Webpack configuration.

To handle this, you should manually filter down to the file extensions that you care about:

let bundles = getBundles(stats, modules);

let styles = bundles.filter(bundle => bundle.file.endsWith('.css'));
let scripts = bundles.filter(bundle => bundle.file.endsWith('.js'));

res.send(`
  <!doctype html>
  <html lang="en">
    <head>
      ...
      ${styles.map(style => {
        return `<link href="/dist/${style.file}" rel="stylesheet"/>`
      }).join('\n')}
    </head>
    <body>
      <div id="app">${html}</div>
      <script src="/dist/main.js"></script>
      ${scripts.map(script => {
        return `<script src="/dist/${script.file}"></script>`
      }).join('\n')}
    </body>
  </html>
`);

More Repositories

1

the-super-tiny-compiler

⛄ Possibly the smallest compiler ever
JavaScript
25,786
star
2

babel-handbook

📘 A guided handbook on how to use Babel and how to create plugins for Babel.
11,881
star
3

itsy-bitsy-data-structures

🏰 All the things you didn't know you wanted to know about data structures
JavaScript
8,574
star
4

unstated

State so simple, it goes without saying
JavaScript
7,821
star
5

spectacle-code-slide

🤘 Present code with style
JavaScript
4,170
star
6

unstated-next

200 bytes to never think about React state management libraries ever again
TypeScript
4,092
star
7

tinykeys

A tiny (~400 B) & modern library for keybindings.
HTML
3,362
star
8

babel-react-optimize

🚀 A Babel preset and plugins for optimizing React code.
JavaScript
1,680
star
9

tailwindcss-animate

A Tailwind CSS plugin for creating beautiful animations
JavaScript
1,084
star
10

glow

Make your Flow errors GLOW
JavaScript
699
star
11

create-react-context

Polyfill for the proposed React context API
JavaScript
695
star
12

json-parser-in-typescript-very-bad-idea-please-dont-use

JSON Parser written entirely in TypeScript's type system
TypeScript
424
star
13

react-gridlist

A virtual-scrolling GridList component based on CSS Grids
TypeScript
421
star
14

favorite-software

🌟 Best software for developers and power users.
355
star
15

marionette-wires

:shipit: An opinionated example application built with Marionette.js.
JavaScript
325
star
16

pretty-format

✨ Stringify any JavaScript value
304
star
17

ghost-lang

👻 A friendly little language for you and me.
300
star
18

documentation-handbook

How to write high-quality friendly documentation that people want to read.
268
star
19

roast-my-deps

Your dependencies are bad and you should feel bad
JavaScript
265
star
20

bey

Simple immutable state for React using Immer
JavaScript
260
star
21

tickedoff

Tiny library (<200B gzip) for deferring something by a "tick"
JavaScript
217
star
22

react-jeff

A Good Form Library
TypeScript
213
star
23

react-performance-observer

Get performance measurements from React Fiber
JavaScript
210
star
24

gender-regex

Regex to test for valid genders
JavaScript
193
star
25

anti-fascist-mit-license

MIT license with additional text to prohibit use by fascists
187
star
26

purposefile

Make sure every file in your repo is exactly where it should be
TypeScript
168
star
27

react-loadable-example

Example project for React Loadable
JavaScript
149
star
28

bootcamp

👢 Jasmine-style BDD testing written in Sass for Sass.
CSS
141
star
29

write-files-atomic

Write many files atomically
JavaScript
124
star
30

sarcastic

Cast unknown values to typed values
JavaScript
98
star
31

ninos

Simple stubbing/spying for AVA
JavaScript
96
star
32

repo-growth

Measure how fast your repo is growing using cloc
JavaScript
89
star
33

workspaces-run

Run tasks/scripts across Yarn/Lerna/Bolt/etc workspaces.
TypeScript
88
star
34

license

The MIT license (with personal exceptions)
86
star
35

scritch

A small CLI to help you write sharable scripts for your team
JavaScript
84
star
36

react-markers

Add markers to your React components for easy testing with actual DOM elements
JavaScript
80
star
37

assert-equal-jsx

assertEqualJSX
JavaScript
78
star
38

proposal-promise-prototype-inspect

Proposal for Promise.prototype.inspect
JavaScript
78
star
39

globby-cli

User-friendly glob matching CLI
JavaScript
76
star
40

spawndamnit

Take care of your spawn()
JavaScript
76
star
41

grob

grep, but in JavaScript... I've truly outdone myself.
JavaScript
72
star
42

react-required-if

React PropType to conditionally add `.isRequired` based on other props
JavaScript
71
star
43

havetheybeenpwned

Test if your user's password has been pwned using the haveibeenpwned.com API
JavaScript
69
star
44

react-prop-matrix

Render something using every possible combination of props
JavaScript
68
star
45

renderator

JavaScript
65
star
46

dark-mode-github-readme-logos

How to make logos in your README that support GitHub's new dark mode
64
star
47

reduxxx

Redux, explicit.
TypeScript
64
star
48

babel-plugin-react-pure-components

Optimize React code by making pure classes into functions
JavaScript
61
star
49

react-test-renderer

[DEPRECATED] A lightweight solution to testing fully-rendered React Components
JavaScript
58
star
50

fixturez

Easily create and maintain test fixtures in the file system
JavaScript
58
star
51

ballistic

🔨 Utility-Belt Library for Sass
CSS
56
star
52

enable-npm-2fa

A script for enabling 2FA on all of your npm packages
JavaScript
55
star
53

cirbuf

A tiny and fast circular buffer
TypeScript
53
star
54

VisibilityObserver

Experimental API for observing the visible box of an element
TypeScript
51
star
55

dependency-free

An experiment to unify/speed up CI/local development via small Docker containers
TypeScript
49
star
56

naw

Your very own containerized build system!
TypeScript
47
star
57

react-stylish

🎀 Make your React component style-able by all
JavaScript
47
star
58

tested-components

Browser integration testing utils for styled-components
JavaScript
41
star
59

jamie.build

the website
HTML
41
star
60

codeowners-enforcer

Enforce CODEOWNERS files on your repo
Rust
41
star
61

std-pkg

The Official package.json Standard™ for Npm® endorsed fields
JavaScript
41
star
62

babel-plugin-private-underscores

Make _classMembers 'private' using symbols
JavaScript
39
star
63

userscript-github-disable-turbolinks

A userscript to disable GitHub turbolinks to force full page navigations
JavaScript
39
star
64

git-workflow

Git workflow for teams
38
star
65

pride

👬 PrideJS logo
38
star
66

babel-plugin-import-inspector

Babel plugin to report dynamic imports with import-inspector with metadata about the import
JavaScript
38
star
67

revalid

Composable validators
JavaScript
37
star
68

ci-parallel-vars

Get CI environment variables for parallelizing builds
JavaScript
37
star
69

crowdin-sync

🌏 How to setup Crowdin to sync with GitHub
Ruby
37
star
70

incremental-dom-react-helper

Helper to make Google's incremental-dom library work with React's compile target today.
JavaScript
36
star
71

guarded-string

Prevent accidentally introducing XSS holes with the strings in your app
JavaScript
36
star
72

babel-plugin-hash-strings

Replace all instances of "@@strings like this" with hashes.
JavaScript
35
star
73

react-module-experiment

JavaScript
34
star
74

task-graph-runner

Run async tasks with dependencies
JavaScript
34
star
75

json-peek

Stringify JSON *just enough* to see what it is
JavaScript
33
star
76

babel-plugin-ken-wheeler

Code like you dope
JavaScript
33
star
77

how-to-build-a-compiler

How to build a compiler – THE TALK
HTML
33
star
78

js-memory-heap-profiling

JavaScript
32
star
79

backbone.service

A simple service class for Backbone.
JavaScript
31
star
80

dep-size-inspect

JavaScript
29
star
81

pffffff

pfffffffffffffffffffff whatever
JavaScript
28
star
82

shimiteer

Puppeteer API shim for other browsers using WebdriverIO
JavaScript
27
star
83

better-directory-sort

Improved sorting order for directory entities
JavaScript
27
star
84

isolated-core-demo

JavaScript
27
star
85

graph-sequencer

Sort items in a graph using a topological sort while resolving cycles with priority groups
JavaScript
27
star
86

import-inspector

Wrap dynamic imports with metadata about the import
JavaScript
26
star
87

backbone-routing

Simple router and route classes for Backbone.
JavaScript
26
star
88

flow-shut-up

Add inline Flow comments to make Flow shut up about errors
JavaScript
25
star
89

proposal-promise-settle

This repository is a work in progress and not seeking feedback yet.
JavaScript
22
star
90

tumblr-downloader

Download all your female-presenting nipples from Tumblr
JavaScript
22
star
91

backbone.storage

A simple storage class for Backbone Models and Collections.
JavaScript
22
star
92

parcel-rust-example

Example of using Rust code in Parcel
HTML
22
star
93

temperment

Get a random temporary file or directory path that will delete itself
JavaScript
22
star
94

is-mergeable

Check if a GitHub Pull Request is in a (most likely) mergeable state
JavaScript
22
star
95

gud

Create a 'gud nuff' (not cryptographically secure) globally unique id
JavaScript
21
star
96

min-indent

Get the shortest leading whitespace from lines in a string
JavaScript
20
star
97

babel-setup-react-transform

Example Babel project using babel-plugin-react-transform
JavaScript
20
star
98

codeowners-utils

Utilities for working with CODEOWNERS files
TypeScript
19
star
99

my-react

Ideas for React APIs
JavaScript
18
star
100

LibManUal

Shell
18
star