Netlify Build is a new, pluggable tool for running builds locally and in Netlify CI. It introduces Build Plugins, which are now in public beta. Learn how to enable your site to use Netlify Build and Build Plugins in the Netlify docs.
Expand Table of Contents
Netlify Build Plugins extend the functionality of the Netlify Build process. You can install plugins made by others, or write your own. You can save them locally in your repository, or share them with others via npm.
For more information on installing, managing, and running published Build Plugins on your Netlify site, visit the Netlify docs.
The content in this repository focuses on how to build your own plugins.
Quite a lot! Community members have already created several plugins to perform a variety of tasks during the build, including:
- controlling how files are cached between builds
- checking for broken links in a site after building
- importing and converting data from external sources
- analyzing and optimizing site asset handling for better runtime performance
- generating content like sitemaps, RSS feeds, and search indexes
Plugins are plain JavaScript objects with event handlers for the different events happening during builds.
For example, the onPreBuild
event handler runs before your build command. Or the onPostBuild
event handler runs
after your site build has completed.
Event | Description |
---|---|
β© βββ βββ βββ onInit βββ βββ βββ | Runs before anything else |
β© βββ βββ βββ onPreBuild βββ βββ βββ | Before build commands are executed |
β© βββ βββ βββ onBuild βββ βββ βββ | Build commands are executed |
β© βββ βββ βββ onPostBuild βββ βββ βββ | After Build commands are executed |
β© βββ βββ βββ onSuccess βββ βββ βββ | Runs on build success |
β© βββ βββ βββ onError βββ βββ βββ | Runs on build error |
π βββ onEnd βββ βββ βββ | Runs on build error or success |
A plugin consists of two files:
-
A
manifest.yml
file in the package root with the plugin's name at minimum:# manifest.yml name: netlify-plugin-hello-world
-
A JavaScript object like so:
// index.js module.exports = { onPreBuild: () => { console.log('Hello world from onPreBuild event!') }, }
The plugin defined above will log out Hello world from onPreBuild event!
right before the site's build commands are
run.
The index.js
file runs in a regular Node.js environment and can use any
Node.js core methods and modules.
Environment variables can be accessed with
process.env
.
Save the index.js
file locally to a ./plugins/netlify-plugin-hello-world
. This will allow us to use the plugin in
the next step.
To leverage this plugin we have just created, we need to declare it in our Netlify configuration file.
Plugins are declared as top-level [[plugins]]
tables in your netlify.toml
file.
# netlify.toml
[[plugins]]
package = "./plugins/netlify-plugin-hello-world"
(Note that each plugin you add to the netlify.toml
file has its own [[plugins]]
line.)
Now that the plugin is declared, we can verify it's loading correctly with the netlify build --dry
command. This
execute a "dry run" of our build and show us the plugins & commands that will execute for a real build.
netlify build --dry
Notice how our onPreBuild
event handler from our netlify-plugin-hello-world
is listed in the things that execute.
Now, let's run the build!
netlify build
This will execute our onPreBuild
function.
If your plugin requires additional values from the user to do things, you can specify these requirements in an inputs
array in the plugin's manifest.yml
file:
# manifest.yml
name: netlify-plugin-hello-world
inputs:
- name: foo
- name: fizz
When you or a user install the plugin, the input names are used as keys with user-supplied values in the site
netlify.toml
file:
# netlify.toml
[[plugins]]
package = "./plugins/netlify-plugin-hello-world"
[plugins.inputs]
foo = "bar"
fizz = "pop"
These inputs
values are passed into the plugin when the event handlers are being executed.
To access them in your plugin code you can:
// index.js
module.exports = {
onPreBuild: ({ inputs }) => {
console.log('Hello world from onPreBuild event!')
console.log(inputs.foo) // bar
console.log(inputs.fizz) // pop
},
}
The plugin inputs can be validated using the inputs
property in the plugin manifest.yml
file:
# manifest.yml
name: netlify-plugin-hello-world
inputs:
- name: foo
required: true
- name: fizz
default: 5
The inputs
property is an array of objects with the following members:
name
{string}
: Name of the input. Required.required
{boolean}
default
{any}
: Default value.
It is recommended to validate your plugin inputs and assign default values using the inputs
property instead of doing
it inside event handlers.
Inside of each event handler there is a constants
key.
// index.js
module.exports = {
onPreBuild: ({ constants }) => {
console.log(constants)
},
}
The constants
key contains the following values:
CONFIG_PATH
Path to the Netlify configuration filePUBLISH_DIR
Directory that contains the deploy-ready HTML files and assets generated by the buildFUNCTIONS_SRC
The directory where function source code livesFUNCTIONS_DIST
The directory where built serverless functions are placed before deploymentIS_LOCAL
Boolean indicating whether the build was run locally (Netlify CLI) or in the production CISITE_ID
The Netlify Site ID
Exceptions thrown inside event handlers are reported in logs as bugs. You should handle errors with try
/catch
blocks
and use utils.build
:
// index.js
module.exports = {
onPreBuild: ({ utils }) => {
try {
badMethod()
} catch (error) {
utils.build.failBuild('Failure message')
}
},
}
The following methods are available depending on the error's type:
utils.build.failBuild('message')
: fails the build - the build in your dashboard would show βFailedβ. Use this to indicate something went wrong.utils.build.failPlugin('message')
: fails the plugin but not the build.utils.build.cancelBuild('message')
: cancels the build - the dashboard would show βCancelledβ for that build. Use this to indicate that the build is being cancelled as planned.
This works inside async
event handlers as well.
utils.build.failBuild()
, utils.build.failPlugin()
and utils.build.cancelBuild()
can specify an options object with
the following properties:
error
: the originalError
instance. Its stack trace will be preserved and its error message will be appended to the'message'
argument.
// index.js
module.exports = {
onPreBuild: ({ utils }) => {
try {
badMethod()
} catch (error) {
utils.build.failBuild('Failure message', { error })
}
},
}
Some plugins trigger different events depending on the user's inputs
. This can be achieved by returning the plugin
object from a function instead.
// index.js
module.exports = function helloWorldPlugin(inputs) {
if (inputs.before) {
return {
onPreBuild: () => {
console.log('Hello world from onPreBuild event!')
},
}
} else {
return {
onPostBuild: () => {
console.log('Hello world from onPostBuild event!')
},
}
}
}
The following properties in package.json
should be added:
name
should start withnetlify-plugin-
(such asnetlify-plugin-example
or@scope/netlify-plugin-example
). It should match the pluginname
field. It is recommended for the GitHub repository to be named like this as well.keywords
should contain thenetlify
andnetlify-plugin
keywords. The same applies to GitHub topics. This helps users find your plugin.repository
andbugs
should be defined. Those are displayed to users when an error occurs inside your plugin.
There is a plugins directory of community-created plugins over at https://github.com/netlify/plugins.
To add a plugin, add information to the plugins.json file.
The content of this file is also used to generate the Plugins directory in the Netlify UI.
Thanks for contributing!
Please see CONTRIBUTING.md for instructions on how to set up and work on this repo itself.