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

docs: plugin authoring workflow overview pages #20847

Merged
merged 11 commits into from
Jan 30, 2020
Merged
58 changes: 51 additions & 7 deletions docs/docs/creating-a-local-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,68 @@ title: Creating a Local Plugin

If a plugin is only relevant to your specific use-case, or if you’re developing a plugin and want a simpler workflow, a locally defined plugin is a convenient way to create and manage your plugin code.

## Project structure for a local plugin

Place the code in the `plugins` folder in the root of your project like this:

```text
plugins
└── my-own-plugin
└── package.json
```
/my-gatsby-site
└── gatsby-config.js
└── /src
└── /plugins
└── /my-own-plugin
└── package.json
```

The plugin also needs to be added to your `gatsby-config.js`, because there is no auto-detection of plugins. It can be added alongside any other 3rd party Gatsby plugins already included in your config.

For the plugin to be discovered when you run `gatsby develop`, the plugin's root folder name needs to match the name used in the `gatsby-config.js` (_not_ the _name_ it goes by in your `package.json` file). For example, in the above structure, the correct way to load the plugin is:

```javascript:title=gatsby-config.js
module.exports = {
plugins: [
`gatsby-third-party-plugin`,
`my-own-plugin`, // highlight-line
],
}
```

**NOTE:** You still need to add the plugin to your `gatsby-config.js`. There is no auto-detection of local plugins.
Then the plugin can begin to hook into Gatsby through Node and SSR APIs.
gillkyle marked this conversation as resolved.
Show resolved Hide resolved
gillkyle marked this conversation as resolved.
Show resolved Hide resolved

**NOTE:** For the plugin to be discovered, the plugin's root folder name is the value that needs to be referenced in order to load it (_not_ its _name_ in its package.json file). For example, in the above structure, the correct way to load the plugin is:
## Developing a local plugin that is outside your project

Your plugin doesn't have to be in your project in order to be tested or worked on. If you'd like to [decouple](/docs/glossary#decoupled) your plugin from your site you can follow one of the methods described below. This is a useful thing to do if you want to publish the plugin as its own package, or test/develop a forked version of a community authored plugin.

### Using `require.resolve` and a filepath

Including a `plugins` folder is not the only way to reference a local plugin. Alternatively, you can include a plugin in your `gatsby-config.js` file by directly referencing its path (relative to the `gatsby-config.js` file) with `require`.

```javascript:title=gatsby-config.js
module.exports = {
plugins: ["my-own-plugin"],
plugins: [
`gatsby-plugin-react-helmet`,
// highlight-start
{
// including a plugin from outside the plugins folder needs the path to it
resolve: require.resolve(`../path/to/gatsby-local-plugin`),
},
// highlight-end
],
}
```

### Using `npm link` or `yarn link`

You can use [`npm link`](https://docs.npmjs.com/cli/link.html) or [`yarn link`](https://yarnpkg.com/lang/en/docs/cli/link/) to reference a package from another location on your machine.

By running `npm link ../path/to/my-plugin` in the root of your Gatsby site, your computer will create a symlink to your package.

This is a similar process to setting up yarn workspaces for development with Gatsby themes (which is the recommended approach for developing themes). You can read how to setup a site in this manner in the [Building a Theme guide](/tutorial/building-a-theme/#set-up-yarn-workspaces).

**Note**: See an example of using a local plugin from the plugins folder, with `require.resolve`, and `npm link` in [this example repository](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-multiple-local-plugins).

## Compilation and processing with Babel

Like all `gatsby-*` files, the code is not processed by Babel. If you want
to use JavaScript syntax which isn't supported by your version of Node.js, you
can place the files in a `src` subfolder and build them to the plugin folder
Expand Down
60 changes: 48 additions & 12 deletions docs/docs/loading-plugins-from-your-local-plugins-folder.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,61 @@
title: Loading Plugins from Your Local Plugins Folder
---

Gatsby can also load plugins from your website's local plugins folder which is a folder named `plugins` in the website's root directory.
Gatsby can load plugins from your website's local plugins folder, which is a folder named `plugins` in the website's root directory.

```javascript:title=gatsby-config.js
module.exports = {
plugins: [`gatsby-local-plugin`],
}
Consider this example project structure which includes a local plugin called `gatsby-local-plugin`:

```
/my-gatsby-site
└── /src
└── /pages
└── /components
<!-- highlight-start -->
└── /plugins
└── /gatsby-local-plugin
└── /package.json
└── /gatsby-node.js
<!-- highlight-end -->
└── gatsby-config.js
└── gatsby-node.js
└── package.json
```

If you want to reference a plugin that is not in the plugins folder then you could use something like the following:
Like the name of the plugins folder implies, you can include multiple plugins in your local plugin folder.

Including a local plugin in your plugins folder also requires a configuration step (similar to a third-party plugin you've installed in your `node_modules` folder by running `npm install`); just as plugins installed from npm need to be included in your `gatsby-config`, you need to add the name of your local plugin to the plugins array as well:

```javascript:title=gatsby-config.js
module.exports = {
plugins: [
// Shortcut for adding plugins without options.
"gatsby-plugin-react-helmet",
{
// Standard plugin with options example
resolve: require.resolve(`/path/to/gatsby-local-plugin`),
},
`gatsby-third-party-plugin`,
`gatsby-local-plugin`, // highlight-line
],
}
```

## Verifying your plugin is loading

To verify that your plugin is available for use in your Gatsby site, you can add a small snippet of code to a `gatsby-node.js` file (you may need to add the `gatsby-node.js` file if there isn't one already) in the root of your plugin:

```javascript:title=plugins/gatsby-local-plugin/gatsby-node.js
exports.onPreInit = () => {
console.log("Testing...")
}
```

_The [`onPreInit` API](/docs/node-apis/#onPreInit) is the first Node API called by Gatsby right after plugins are loaded._

Then, when running your site in develop or build mode, you should see "Testing..." logged in your terminal:

```sh
success open and validate gatsby-configs - 0.051s
success load plugins - 1.047s
Testing... // highlight-line
success onPreInit - 0.023s
...
```

## Loading local plugins from _outside_ the plugins folder

If you want to reference a plugin that is not in the plugins folder, there are several options that are described in more detail in the [Creating a Local Plugin guide](/docs/creating-a-local-plugin/).
7 changes: 5 additions & 2 deletions docs/docs/naming-a-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Naming a Plugin

## Plugin title naming conventions

There are four standard plugin naming conventions for Gatsby:
There are five standard plugin naming conventions for Gatsby:

- **`gatsby-source-*`** — a source plugin loads data from a given source (e.g. WordPress, MongoDB, the file system). Use this plugin type if you are connecting a new source of data to Gatsby.
- Example: [`gatsby-source-contentful`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-contentful)
Expand All @@ -14,6 +14,9 @@ There are four standard plugin naming conventions for Gatsby:
- Docs: [creating a transformer plugin](/docs/creating-a-transformer-plugin/)
- **`gatsby-[plugin-name]-*`** — if a plugin is a plugin for another plugin 😅, it should be prefixed with the name of the plugin it extends (e.g. if it adds emoji to the output of `gatsby-transformer-remark`, call it `gatsby-remark-add-emoji`). Use this naming convention whenever your plugin will be included as a plugin in the `options` object of another plugin.
- Example: [`gatsby-remark-images`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-remark-images)
- **`gatsby-theme-*`** — this naming convention must be used for [Gatsby themes](/docs/themes/), which are a type of plugin.
- Docs: [creating a remark plugin](/docs/remark-plugin-tutorial/)
- **`gatsby-theme-*`** — this naming convention **must** be used for [Gatsby themes](/docs/themes/), which are a type of plugin. Without following this naming convention, the plugin will not be recognized as a theme and it will not be able to utilize the powerful [shadowing](/docs/themes/shadowing/) feature of themes.
- Example: [`gatsby-theme-blog`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-blog)
- Docs: [creating a theme](/tutorial/building-a-theme/)
- **`gatsby-plugin-*`** — this is the most general plugin type. Use this naming convention if your plugin doesn’t meet the requirements of any other plugin types.
- Example: [`gatsby-plugin-sharp`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-sharp)
4 changes: 2 additions & 2 deletions docs/docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: Plugins

Gatsby plugins are Node.js packages that implement Gatsby APIs. For larger, more complex sites, plugins let you modularize your site customizations into site-specific plugins.

There are many types of Gatsby plugins, including data sourcing, SEO, responsive images, offline support, Sass support, sitemaps, RSS feeds, TypeScript, Google Analytics, and more. You can also [make your own plugins](/docs/creating-plugins/)!
There are many types of Gatsby plugins, including [data sourcing](/plugins/?=gatsby-source), [SEO](/plugins/?=seo), [responsive images](/packages/gatsby-image/?=gatsby-image), [offline support](/packages/gatsby-plugin-offline/), [Sass support](/packages/gatsby-plugin-sass/), [sitemaps](/packages/gatsby-plugin-sitemap/), [RSS feeds](/packages/gatsby-plugin-feed/), [TypeScript](/packages/gatsby-plugin-typescript/), [Google Analytics](/packages/gatsby-plugin-google-analytics/), and more. You can also [make your own plugins](/docs/creating-plugins/)!

Gatsby themes are a type of plugin that include a `gatsby-config.js` file and add **pre-configured** functionality, data sourcing, and/or UI code to Gatsby sites. To learn more about theme use cases and APIs, check out the [themes section of the docs](/docs/themes/).
Gatsby themes are a type of plugin that include a `gatsby-config.js` file and add **pre-configured** functionality, data sourcing, and/or UI code to Gatsby sites. To learn more about theme use cases and APIs, check out the [themes section of the docs](/docs/themes/). To learn about how plugins differ from themes and starters refer to the [Plugins, Themes, & Starters conceptual guide](/docs/plugins-themes-and-starters/).

Here are the guides in the Plugins section of the docs:

Expand Down
4 changes: 4 additions & 0 deletions examples/using-local-plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ This example uses a [local plugin](/docs/loading-plugins-from-your-local-plugins
3. Use the [`createNode` action](/docs/actions/#createNode) to add the data to Gatsby’s GraphQL layer

The [`gatsby-node.js` file](./plugins/gatsby-source-pokeapi/gatsby-node.js) of the local plugin includes detailed comments on the process.

## Examples loading multiple local plugins outside the plugins folder

To see how to load multiple plugins from outside the plugins folder, refer to the [`using-multiple-local-plugins` example repository](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-multiple-local-plugins).
108 changes: 108 additions & 0 deletions examples/using-multiple-local-plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Using Gatsby with Local Plugins

This is an example repository demonstrating different ways to load plugins in a Gatsby site.

## Running the Example

The actual Gatsby site to run is in the `gatsby-site-using-local-plugins` folder.

Navigate into the example site from the root of this example with this command:
gillkyle marked this conversation as resolved.
Show resolved Hide resolved

```sh
cd gatsby-site-using-local-plugins
```

You'll need to install dependencies for the site by running:

```sh
npm install
```

Then run `gatsby develop`:

```sh
gatsby develop
```

You should then see the output listed below. Showing how the code for each plugin is run sequentially thanks to the Node API implemented.
gillkyle marked this conversation as resolved.
Show resolved Hide resolved

```sh
$ gatsby develop
success open and validate gatsby-configs - 0.051s
success load plugins - 1.047s
logging to the console from plugins folder
logging to the console from a plugin in another project with require.resolve
logging to the console from site's gatsby-node
success onPreInit - 0.023s
```

For the config to load all the plugins you'll need to uncomment the line in the `gatsby-site-using-multiple-local-plugins/gatsby-config.js` file for `gatsby-plugin-console-log-c`:

```javascript:title=gatsby-site-using-multiple-local-plugins/gatsby-config.js
module.exports = {
siteMetadata: {
title: `Using Multiple Local Plugins`,
description: `An example Gatsby site utilizing multiple local plugins`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
// including a plugin from the plugins folder
`gatsby-plugin-console-log-a`,
{
// including a plugin from outside the plugins folder needs the path to it
resolve: require.resolve(`../gatsby-plugin-console-log-b`),
},
// including a plugin with yarn or npm link
// in order for this plugin to be found when you run gatsby develop
// you first need to run `npm link ../gatsby-plugin-console-log-c` in the `gatsby-site-using-local-plugins` root folder
`gatsby-plugin-console-log-c`, // highlight-line
],
}
```

And then run:

```sh:title=gatsby-site-using-multiple-local-plugins
npm link ../gatsby-plugin-console-log-c
```

When you run `gatsby develop` now, you should see the last plugin logging another line:

```diff
$ gatsby develop
success open and validate gatsby-configs - 0.051s
success load plugins - 1.047s
logging to the console from plugins folder
logging to the console from a plugin in another project with require.resolve
+ logging to the console from a plugin in another project with npm/yarn link
logging to the console from site's gatsby-node
success onPreInit - 0.023s
```

## Context

The same `gatsby-plugin-console-log` plugin is implemented 3 times (and 1 additional time in the site's `gatsby-node`), each one hooking into the `onPreInit` Gatsby Node API to log a simple message to the console when the site is run in develop or build mode.

The code that is implemented looks similar to this:

```javascript
exports.onPreInit = () => {
console.log("logging to the console...")
}
```

### 4 patterns implemented

The 4 ways the code is run are:

1. Inside the site's `gatsby-node.js`
2. In a plugin in the plugins folder (`gatsby-plugin-console-log-a`)
3. In a separate project folder but included with `require.resolve` in the config (`gatsby-plugin-console-log-b`)
4. In a separate project folder but included via `npm link` (`gatsby-plugin-console-log-c`)

You can read about these methods in the [loading local plugins doc](https://www.gatsbyjs.org/docs/loading-plugins-from-your-local-plugins-folder/).

## More advanced local plugin example

For another example featuring a more sophisticated local plugin, you can refer to the [`using-local-plugins` example repository](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-local-plugins).
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exports.onPreInit = () => {
console.log("logging to the console from a plugin in another project with require.resolve")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// noop
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "gatsby-plugin-console-log-b",
"version": "1.0.0",
"description": "Log stuff in a Gatsby site's build process",
"main": "index.js",
"license": "MIT"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exports.onPreInit = () => {
console.log("logging to the console from a plugin in another project with npm/yarn link")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// noop
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "gatsby-plugin-console-log-c",
"version": "1.0.0",
"description": "Log stuff in a Gatsby site's build process",
"main": "index.js",
"license": "MIT"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# dotenv environment variable files
.env*

# gatsby files
.cache/
public

# Mac files
.DS_Store

# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity
Loading