This code creates a redirect for every entry inside the redirects array that you import from redirects.json.
Since redirects are server side, your hosting platform must handle them for you. For this reason, you can’t test redirects locally while developing.
The most popular hosting options — Gatsby Cloud and Netlify — handle redirects differently. Depending on your platform of choice, you need to install the needed plugin.
The syntax for splat redirects on Gatsby Cloud differs from Netlify. To redirect all requests from /blog/ subdirectory to /posts/ subdirectory, use an asterisk (*).
Gatsbyjs Node API provides great many ways to create static pages for your application. The thing I like most about it is, the complete control it gives. Essentially to create a page, we need to
Supply path or slug of the page.
A react component template.
Data.
NOTE: The article is written for gatsbyjs v2, and it may still work for v1.
Gatsby doesn't care how and where the data came from, it can be from a graphql query or maybe something else too. It just creates a page at the provided path, passes the data to your react component and again you are in control of how to present the data.
So I was in a situation where I needed to iterate over a multiple thing, which was based on promise interface and I needed createPages to wait for all the promise to resolve. Basically I was:
Fetching some markdown files using graphql query.
Fetching some directory from the file-system using Nodejs fs API.
This is the solution I came up with.
USE Promise.all INTERFACE
Under gatsby-node.js file, we usually define createPages like this:
As we can see, here we are just returning one single Promise, we get with graphql function and gatsby is taking care of waiting till it is resolved. This is just how Promise work, they don't resolve until we call resolve() or all chainables are passed.
So naturally the right way to wait for multiple queries would be to have multiple Promise and return a Promise.all([promiseOne, promiseTwo]). Let's see an example
// Create pages for docs and docRoots
exports.createPages=({ actions, graphql })=>{const{ createPage }= actions;const docTemplate = path.resolve('src/templates/docTemplate.js');const docRootTemplate = path.resolve('src/templates/docRootTemplate.js');// Individual doc pages// graphql already returns a promise// so we can use that instead of creating our own Promise instanceconst docs =graphql(`
{
allMarkdownRemark(
filter: { fileAbsolutePath: { glob: "**/docs/**/*.md" } }
sort: { order: DESC, fields: frontmatter___order }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result =>{if(result.errors){
Promise.reject(result.errors);}
result.data.allMarkdownRemark.edges.forEach(({ node })=>{createPage({
path: node.fields.slug,
component: docTemplate,});});});// Doc root pages// This is a `sync` operation, but we are wrapping// inside a Promise, because that's what gatsby Node API// expects.const docRoots =newPromise((resolve, reject)=>{// First get all directories inside docsconst docTypes =dirs(path.resolve(__dirname,'./docs'));if(docTypes && docTypes.length){
docTypes.forEach(docType =>{createPage({
path:`/${docType}/`,
component: docRootTemplate,
context:{
docType,},});});resolve();}else{reject(newError(`No directories found for document roots.`));}});return Promise.all([docs, docRoots]);};
Here we are
Querying through graphql our markdown files.
At the same time, we are querying directories to get child directory and creating pages for them too. Here the operation is synchronous but we are still using promise interface to demonstrate the working of asynchronous operations.
Finally we are returning Promise.all([...]), which would return a promise interface, which in turn, would wait for all the individual Promises we have passed to it.
And that's how it works.
WHAT IF I NEED MULTIPLE graphql QUERIES?
In most of the cases you don't. Just use a single graphql query and extract data from it.
For example, if we were to extract files from src/pages/guide/**/*.md, and src/blog/**/*.md, then instead of writing two queries, we can very much do
and extracting the results using result.data.blogs and result.data.docs.
IMHO, this is the perfectly fine way to have multiple query dependent createPage stuff.
But if, for some reason, you absolutely MUST have parallel running multiple queries, then again you can use the promise interface. Let's convert the same example into multiple queries.
// Create pages for docs and blogs separately using two separate// queries. We use the `graphql` function which returns a Promise// and ultimately resolve all of them using Promise.all(Promise[])
exports.createPages=({ actions, graphql })=>{const{ createPage }= actions;const docTemplate = path.resolve('src/templates/docTemplate.js');const blogTemplate = path.resolve('src/templates/blogTemplate.js');// Individual blogs pagesconst blogs =graphql(`
{
blogs: allMarkdownRemark(
filter: { fileAbsolutePath: { glob: "**/src/pages/blog/*.md" } }
sort: { order: DESC, fields: frontmatter___date }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result =>{if(result.errors){
Promise.reject(result.errors);}// Create blog pages
result.data.blogs.edges.forEach(({ node })=>{createPage({
path: node.fields.slug,
component: blogTemplate,});});});// Individual docs pages
const docs =graphql(`
{
docs: allMarkdownRemark(
filter: {
fileAbsolutePath: { glob: "**/src/pages/project/*.md" }
}
sort: { order: DESC, fields: frontmatter___order }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result =>{if(result.errors){
Promise.reject(result.errors);}// Create doc pages
result.data.docs.edges.forEach(({ node })=>{createPage({
path: node.fields.slug,
component: docTemplate,});});});// Return a Promise which would wait for both the queries to resolve
return Promise.all([blogs, docs]);};
Here we are creating multiple Promisees blogs and docs. Notice we are again just using graphql directly, which actually returns a Promise. We are calling .then() to chain a callback function, under which we are creating the pages through createPage API.
Returning Promise.all([blogs, docs]) ensures that our operation is successfully completed, before gatsby moves to create page files.