Files
flipper/docs/extending/jssetup.md
Anton Nikolaev e165c2cd95 Desktop plugin development workflow
Summary: Updated docs describing workflow for creating Flipper desktop plugins

Reviewed By: passy

Differential Revision: D21129688

fbshipit-source-id: 68921e5d3784e3ab6b3e8397199b10101348a86a
2020-04-23 05:58:39 -07:00

9.2 KiB

id, title
id title
js-setup Desktop Plugin Development

Workflow

In a nutshell, the workflow for creating Flipper Desktop Plugin is the following:

  1. To make your custom plugins discoverable by Flipper, create a directory to contain them, e.g. ~/flipper-plugins, and add this path to the pluginPaths property in the Flipper config (~/.flipper/config.json).
  2. Create a directory for your plugin inside the directory created at step 1, e.g. ~/flipper-plugins/my-plugin.
  3. Define your plugin in the directory created at step 2.
  4. Start a development build of Flipper which will automatically transpile, bundle and load the defined plugin, as well as all other plugins found in the directories specified as pluginPaths in the Flipper config.
  5. Debug your plugin, make necessary changes and verify them in the running Flipper development build instance which will re-load the changed components automatically.
  6. If you want to be sure the plugin works as expected with a release build, you can package it as a tarball and install it from the file system into a released version of Flipper.
  7. Finally, bundle the plugin and publish it to npm, so it can be discovered and installed by any Flipper user.

Dynamically Loading Plugins

Flipper loads and runs plugins it finds in a configurable location. The paths searched are specified in ~/.flipper/config.json. These paths, pluginPaths, should contain one folder for each of the plugins it stores. An example config setting and plugin file structure is shown below:

~/.flipper/config.json:

{
  ...,
  "pluginPaths": ["~/flipper-plugins"]
}

Plugin File example structure:

~ flipper-plugins/
    my-plugin/
      package.json
      src/index.tsx
      dist/bundle.js

Plugin Definition

All Flipper Desktop plugins must be self-contained in a directory. This directory must contain at a minimum package.json and entry source file, e.g.:

  • package.json
  • src/index.tsx

The best way to initialize a JS plugin is to create a directory, and run yarn init inside it. By convention, the name of a Flipper plugin package should start with flipper-plugin-, e.g. flipper-plugin-myplugin.

Make sure that the id field in your package.json is the same as the identifier of the client plugin, e.g. if your Java plugin returns myplugin from its getId() method, the id field in your package.json should also be myplugin.

Flipper has tooling for transpiling and bundling which allows writing plugins in plain ES6 JavaScript, Flow or TypeScript but we recommend you use TypeScript for the best development experience. We also recommend you use the file extension .tsx when using TypeScript which adds support for inline React expressions.

After yarn init finishes, create an src/index.tsx file which will be the entry point to your plugin. An example package.json file could look like this:

Example package.json:

{
  "name": "flipper-plugin-myplugin",
  "id": "myplugin",
  "specVersion": 2,
  "version": "1.0.0",
  "main": "dist/bundle.js",
  "flipperBundlerEntry": "src/index.tsx",
  "license": "MIT",
  "keywords": ["flipper-plugin"],
  "title": "My Plugin",
  "icon": "apps",
  "bugs": {
    "email": "you@example.com"
  },
  "scripts": {
    "prepack": "flipper-pkg bundle"
  }
  "dependencies": {
    "flipper": "latest"
  },
  "devDependencies": {
    "flipper-pkg": "latest"
  }
}

Important attributes of package.json:

  • name Npm package name. Should start with flipper-plugin- by convention, so Flipper plugins can be easily found on npm.

  • specVersion Version of the Flipper plugin specification. Currently, Flipper supports plugins defined using version 2 of the specification which is described in the current section.

  • id Used as the plugin native identifier and must match the mobile plugin identifier.

  • main Points to the plugin bundle which will be loaded by Flipper. The "flipper-pkg" utility uses this field to determine output location during plugin bundling.

  • flipperBundlerEntry Points to the source entry point which will be used for plugin code bundling. "flipper-pkg" takes the path specified in flipperBundlerEntry as source, transpiles and bundles it, and saves the output to the path specified in main.

  • keywords The field must contain the flipper-plugin keyword, otherwise Flipper won't discover the plugin. Additionally, the field can also contain any other keywords for better plugin discoverability.

  • title Shown in the main sidebar as the human-readable name of the plugin.

  • icon Determines the plugin icon which is displayed in the main sidebar. The list of available icons is static for now: https://github.com/facebook/flipper/blob/master/desktop/static/icons.json.

  • bugs Specify an email and/or url, where plugin bugs should be reported.

In index.tsx you will define the plugin in JavaScript. This file must export a default class that extends FlipperPlugin. Browse our JS API docs to see what you can do, and make sure to check out our UI Component Library for lots of pre-made components.

Example index.tsx:

import {FlipperPlugin} from 'flipper';

export default class extends FlipperPlugin {
  render() {
    return 'hello world';
  }
}

npm dependencies

If you need any dependencies in your plugin, you can install them using yarn add.

Development Build

A Flipper development build should be used for plugin debugging. It is also used for Flipper core development and provides the following features:

  • Automatic transpilation and bundling of loaded plugins: ES6, Flow, TypeScript, JSX.
  • Automatic refresh after code changes.
  • React and Redux Dev Tools.
  • Debugging using Chrome Dev Tools or Visual Studio Code.

Prerequisites for Flipper development build:

  • node ≥ 8
  • yarn ≥ 1.5
  • git
  • watchman

To start a development build, clone the Flipper repository, install the dependencies and execute the start script:

git clone https://github.com/facebook/flipper.git
cd flipper/desktop
yarn
yarn start

Transpiling and Bundling

As we already mentioned, the Flipper development build automatically transpiles and bundles plugins on loading. It is capable of all the ES6 goodness, Flow annotations, TypeScript, as well as JSX and applies the required babel-transforms.

The Flipper release build, in contrast, does not transpile or bundle plugins on loading. For production usage, plugins should be bundled before publishing using flipper-pkg. This utility applies the same modifications as the plugin loader of the development build.

The tool is published to npm and can be installed as a devDependency for the plugin package, or as a global CLI tool:

yarn global add flipper-pkg

Then, to bundle the plugin, execute the following command in its folder:

flipper-pkg bundle

This command reads the package.json, takes the path specified in the flipperBundleEntry field as entry point, transpiles and bundles all the required code, and outputs the produced bundle to the path specified in field main.

You can get the list of other available commands by invoking flipper-pkg help, and get detailed description for any command by invoking flipper-pkg help [COMMAND]. You can also check README on npmjs.com for usage details: https://www.npmjs.com/package/flipper-pkg.

Packaging and Publishing

Publishing to npm

Flipper plugins are essentially standard npm packages. So you can publish them by executing yarn publish or npm publish in the plugin directory. The only requirements are:

  1. package.json and code must follow the Flipper plugin specification
  2. code must be bundled using "flipper-pkg" before packing or publishing. This can be done by executing flipper-pkg bundle on prepack step:
    {
      ...
      "devDependencies": {
        ...
        "flipper-pkg": "latest"
      },
      "scripts": {
        ...
        "prepack": "flipper-pkg bundle"
      }
    }
    

Packaging to File

To package plugin as a tarball, you can use the same command as for packaging any other npm package, e.g. yarn pack or npm pack.

"flipper-pkg" also provides a convenient command pack which:

  1. Installs the plugin dependencies
  2. Bundles the plugin
  3. Creates the tarball and saves it at the specified location

E.g. to package plugin located at ~/flipper-plugins/my-plugin to ~/Desktop, execute the following command:

flipper-pkg pack ~/flipper-plugins/my-plugin -o ~/Desktop

Installation from File

It is possible to install plugins into Flipper from tarballs. This is useful in cases when you need to try a plugin version which is not published to npm, or if you want to distribute plugin privately:

  1. Launch Flipper
  2. Click the "Manage Plugins" button in the bottom-left corner
  3. Select the "Install Plugins" tab in the opened sheet
  4. Specify the path to the plugin package (or just drag and drop it) and click "Install"