Plugins functions are executed throughout the lifecycle of a react-static build in the order below:
A synchronous function to modify the resolved config object during build or export.
- Arguments:
config- Thestatic.config.jsstate- The current state of the cli
- Returns a new or modified
configobject
afterGetConfig: (previousConfig, state) => {
// Return a new config
return newConfig
}An async function to modify the CLI state before browser plugins are prepared.
- Arguments:
state- The current state of the cli
- Returns the new CLI
state
beforePrepareBrowserPlugins: async state => {
// Use or modify the CLI state
return newState
}An async function to modify the CLI state after preparing browser plugins.
- Arguments:
state- The current state of the cli
- Returns the new CLI
state
afterPrepareBrowserPlugins: async state => {
// Use or modify the CLI state
return newState
}An async function to modify the CLI state before preparing routes.
- Arguments:
state- The current state of the cli
- Returns the new CLI
state
beforePrepareRoutes: async state => {
// Use or modify the CLI state
return newState
}A synchronous function to modify the route after it has been normalized.
- Arguments:
info{}route- The normalized route after it has been normalizedparent- The parent route
state- The current state of the cli
- Returns the new
normalizedRoute
normalizeRoute: ({ route, parent }, state) => {
// Modify the route
return route
}An async function to modify the CLI state before preparing routes.
- Arguments:
state- The current state of the cli
- Returns the new CLI
state
afterPrepareRoutes: async state => {
// Use or modify the CLI state
return newState
}A synchronous function to modify the webpack config.
- Arguments:
currentWebpackConfig- The current webpack configuration objectstate- The current state of the CLI
- Returns a new webpack configuration object
webpack: (currentWebpackConfig, state) => {
// Return a new config
return newConfig
}Loaders
The default loaders for React Static are available as a convenience object at state.defaultLoaders:
jsLoader- The default loader for all.jsfiles located in your project'ssrcdirectoryjsLoaderExt- The default loader for all other.jsfiles not located in your project'ssrcdirectory.cssLoader- The default style loader that supports importing.cssfiles and usage of css modules.fileLoader- The default catch-all loader for any other file that isn't a.js.jsonor.htmlfile. Usesurl-loaderandfile-loader
Our default loaders are organized like so:
const webpackConfig = {
...
module: {
rules: [{
oneOf: [
jsLoader, // Compiles all project javascript files with babel
jsLoaderExt, // Compiles all external (node_modules) javascript files with babel
cssLoader, // Supports basic css imports and css modules
fileLoader // Catch-all url-loader/file-loader for anything else
}]
}
...
}The source for all default loaders can be found in webpack/rules/ directory.
Note: Usage of the oneOf rule is recommended. This ensures each file is only handled by the first loader it matches, and not any loader. This also makes it easier to reutilize the default loaders, without having to fuss with excludes. Here are some examples of how to replace and modify the default loaders:
Replacing all rules
// node.api.js
export default pluginOptions => ({
webpack: config => {
config.module.rules = [
// Your own rules here...
]
return config
},
})Replacing a default loader for a different one
// node.api.js
export default pluginOptions => ({
webpack: (config, { defaultLoaders }) => {
config.module.rules = [{
oneOf: [
defaultLoaders.jsLoader,
defaultLoaders.jsLoaderExt,
{
// Use this special loader
// instead of the cssLoader
}
defaultLoaders.fileLoader,
]
}]
return config
}
})Adding a plugin
// node.api.js
import AwesomeWebpackPlugin from 'awesome-webpack-plugin'
export default pluginOptions => ({
webpack: config => {
config.plugins.push(new AwesomeWebpackPlugin())
return config
},
})Using multiple transformers
// node.api.js
export default pluginOptions => ({
webpack: [
(config, { defaultLoaders }) => {
config.module.rules = [
{
oneOf: [
defaultLoaders.jsLoader,
defaultLoaders.jsLoaderExt,
defaultLoaders.cssLoader,
{
loader: 'file-loader',
test: /\.(fancyFileExtension)$/,
query: {
limit: 10000,
name: 'static/[name].[hash:8].[ext]',
},
},
defaultLoaders.fileLoader,
],
},
]
return config
},
config => {
console.log(config.module.rules) // Log out the final set of rules
},
],
})Modify the App component before it is rendered to an element via <App />.
- Arguments:
App- TheAppcomponent (not yet rendered to an element via<App />)state- The current state of the CLI
- Returns a new
Appcomponent (not yet rendered to an element)
// node.api.js
export default pluginOptions => ({
afterDevServerStart: async state => {
// Use or modify the CLI state
return newState
},
})An async function to modify the CLI state after starting the development server.
- Arguments:
App- TheAppcomponent (not yet rendered to an element via<App />)state- The current state of the CLI
- Returns a new
Appcomponent (not yet rendered to an element)
// node.api.js
export default pluginOptions => ({
beforeRenderToElement: async (App, state) => {
const NewApp => props => {
return <App {...props} />
}
// You must return the component, not the rendered element!
return NewApp
},
})Modify the rendered <App /> element before it is rendered to HTML.
- Arguments:
app- Theappelement (has already been rendered via<App />)state- The current state of the CLI
- Returns a new react element for the App
// node.api.js
export default pluginOptions => ({
beforeRenderToHtml: async (element, state) => {
// You must return an element (already rendered), not a component
const newApp = <div>{element}</div>
return newApp
},
})Modify the props that will passed to the Document's <html> element.
- Arguments:
props- The current props objectstate- The current state of the CLI
- Returns a new props object
// node.api.js
export default pluginOptions => ({
htmlProps: async (props, state) => {
return {
...props,
myProp: 'hello',
}
},
})Add elements to the <head> of the statically generated page.
- Arguments:
elements- The current array of elements that will be rendered into the head of the document.state- The current state of the CLI
- Returns a new array of elements
// node.api.js
export default pluginOptions => ({
headElements: async (elements, state) => {
return [
...elements,
<link rel="stylesheet" href="..." />,
<link rel="stylesheet" href="..." />,
]
},
})Modify the app html string before it is injected into the Document component.
- Arguments:
html- The apphtmlstring to be injected into the Document componentstate- The current state of the CLI
- Returns a new
htmlstring to be injected into theDocumentcomponent
// node.api.js
export default pluginOptions => ({
beforeHtmlToDocument: async (html, state) => {
// html is a string here. You can do whatever you like with it!
return html
},
})Modify the final html string before it is written to disk.
- Arguments:
html- The finalhtmlstring before it is written to diskstate- The current state of the CLI
- Returns a new final
htmlstring to be written to disk.
// node.api.js
export default pluginOptions => ({
beforeDocumentToFile: async (html, state) => {
// html is a string here. You can do whatever you like with it!
return html
},
})After a completed build and export, run any asynchronous function.
- Arguments:
state- The current state of the CLI
- Returns a new
stateobject
// node.api.js
export default pluginOptions => ({
afterExport: async state => {
// Use or alter the state of the CLI
return state
},
})An array of plugins that this plugin depends on. Follows the same format as static.config.js does for importing plugins and options.
// node.api.js
export default pluginOptions => ({
plugins: [
'another-plugin',
[
'another-plugin-with-options',
{
anOption: true,
},
],
],
})