Skip to content

Gatsby build slow (800 pages) #3790

@gafasstudio

Description

@gafasstudio

Description

We build a website with gatsby (npm run build), the data comes from Contentful and it is build on Netlify. The website has around 800 pages. But it takes 15 minutes to build the site on Netlify and Netlify has a 15min limit. Locally it also takes 10 minutes to build the site, which seems a bit long or is it normal?

Deploy log can be found in the pdf
deploy_log_netlify.txt.pdf

Environment

Gatsby version: 1.9.149
Node.js version: v8.9.4
Operating System: OSX, Linux (Netlify)

File contents (if changed):

gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: `website`,
  },
  plugins: [
    {
      resolve: `gatsby-source-contentful`,
      options: {
        spaceId: `xxxxx`,
[deploy_log_netlify.txt.pdf](https://github.com/gatsbyjs/gatsby/files/1681794/deploy_log_netlify.txt.pdf)



        accessToken: `xxxxx`,
      },
    },
    {
        resolve: `gatsby-source-contentful`,
        options: {
            spaceId: `xxxxx`,
            accessToken: `xxxxxxx`,
        },
    },
    {
      resolve: `gatsby-plugin-nprogress`,
      options: {
        // Setting a color is optional.
        color: `#C2A572`,
        // Disable the loading spinner.
        showSpinner: false,
      },
    },
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        trackingId: "XX-XXXX-XX",
      },
    },
    `gatsby-transformer-remark`,
  ],

};

package.json:

{
  "name": "website",
  "version": "1.0.0",
  "license": "MIT",
  "main": "n/a",
  "dependencies": {
    "@google/maps": "^0.4.5",
    "babel-polyfill": "^6.26.0",
    "blazy": "^1.8.2",
    "bowser": "^1.8.1",
    "classnames": "^2.2.5",
    "contentful-management": "^4.1.1",
    "flickity": "^2.0.10",
    "flickity-bg-lazyload": "^1.0.0",
    "gatsby": "^1.9.77",
    "gatsby-link": "^1.6.20",
    "gatsby-plugin-google-analytics": "^1.0.13",
    "gatsby-plugin-nprogress": "^1.0.8",
    "gatsby-plugin-offline": "^1.0.10",
    "gatsby-source-contentful": "^1.3.18",
    "gatsby-transformer-remark": "^1.7.21",
    "gsap": "^1.20.3",
    "hash-object": "^0.1.7",
    "ie-array-find-polyfill": "^1.1.0",
    "in-view": "^0.6.1",
    "ismobilejs": "^0.4.1",
    "lodash": "^4.16.4",
    "mandrill-api": "^1.0.45",
    "moment": "^2.19.1",
    "netlify-cli": "^1.2.2",
    "progressbar.js": "^1.0.1",
    "prop-types": "^15.5.10",
    "react-click-outside": "^2.3.1",
    "react-document-meta": "^2.1.2",
    "react-flatpickr": "^3.6.0",
    "react-flickity-component": "^1.1.0",
    "react-google-maps": "^9.1.0",
    "react-headrooms": "^1.0.6",
    "react-inview": "^0.0.6",
    "react-inview-js": "^1.2.7",
    "react-markdown": "^2.5.0",
    "react-masonry-component": "^6.0.1",
    "react-places-autocomplete": "^5.4.3",
    "react-player": "^0.25.2",
    "react-progressbar.js": "^0.2.0",
    "react-scrollable-anchor": "^0.5.0",
    "react-visibility-sensor": "^3.11.0",
    "save": "^2.3.1",
    "scrollprogress": "^3.0.2",
    "slash": "^1.0.0",
    "wheel-react": "^1.0.3"
  },
  "scripts": {
    "develop": "npm-run-all --parallel develop:*",
    "develop:gatsby": "gatsby develop",
    "develop:css": "postcss src/css/app.css -o public/app.css -w",
    "develop:css-static": "postcss src/css/app.css -o static/app.css -w",
    "build": "npm-run-all build:gatsby",
    "build:gatsby": "node --max-old-space-size=8192 node_modules/.bin/gatsby build",
    "build:css": "postcss src/css/app.css -o static/app.css",
    "start": "gatsby serve",
    "precommit": "lint-staged",
    "prettify": "prettier --trailing-comma es5 --single-quote --print-width 100 --write \"src/**/*.js\"",
    "prettify:g": "prettier --trailing-comma es5 --single-quote --print-width 100 --write \"gatsby-node.js\"",
    "fix": "eslint --fix src",
    "lint": "eslint src"
  },
  "devDependencies": {
    "babel-eslint": "7.2.3",
    "eslint": "3.19.0",
    "eslint-config-react-app": "^2.0.0",
    "eslint-plugin-flowtype": "2.33.0",
    "eslint-plugin-import": "2.2.0",
    "eslint-plugin-jsx-a11y": "5.0.1",
    "eslint-plugin-react": "7.0.1",
    "gatsby-cli": "^1.1.11",
    "husky": "^0.14.3",
    "jspolyfill-array.prototype.find": "^0.1.3",
    "lint-staged": "^4.1.0",
    "npm-run-all": "^4.1.2",
    "postcss": "^6.0.14",
    "postcss-cli": "^4.1.1",
    "postcss-cssnext": "^3.0.2",
    "postcss-import": "^11.0.0",
    "prettier": "^1.6.1"
  },
  "lint-staged": {
    "src/**/*.js": [
      "prettier --trailing-comma es5 --single-quote --print-width 100 --write",
      "git add"
    ]
  },
  "eslintConfig": {
    "extends": [
      "react-app"
    ],
    "globals": {
      "graphql": false,
      "$": false,
      "google": false,
      "history": false
    }
  }
}

`gatsby-node.js`: const _ = require('lodash');
const Promise = require('bluebird');
const path = require('path');
const slash = require(`slash`);
const storeLocator = require('./node/storeLocator');
const queries = require('./node/queries');

//
function createSinglePages(key, createPage, result, language, slug, conditional = 'id') {
  const template = path.resolve(`./src/templates/${key}.js`);
  _.each(_.filter(result, edge => edge.node.node_locale == language), edge => {
    if (edge.node[conditional]) {
      createPage({
        path: `${language}/${_.replace(slug, ':slug', edge.node.slug)}`,
        component: slash(template),
        context: {
          locale: language,
          id: edge.node.id,
          navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
        },
      });
    }
  });
}

function createWikiPages(key, category, result, slug, createPage, language) {
  var array = _.filter(result, edge => edge.node.type == category);
  array = _.filter(array, edge => edge.node.node_locale == language);
  
  const template = path.resolve(`./src/templates/${key}.js`);
  _.each(array, edge => {
    _.each(edge.node.wikiSubcategorien, category => {
      if (category.id) {
        createPage({
          path: `${language}/${_.replace(slug, ':slug', category.slug)}`,
          component: slash(template),
          context: {
            locale: language,
            id: category.id,
            navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
          },
        });
        _.each(category.wiki, wiki => {
          if (wiki.id) {
            createPage({
              path: `${language}/${_.replace(slug, ':slug', category.slug)}/${wiki.slug}`,
              component: slash(template),
              context: {
                locale: language,
                id: wiki.id,
                navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
              },
            });
          }
        });
      }
    });
  });
}

function AllPagesCreated(totalPages, resolveFn, ttl = 6000000) {
  this.totalPages = totalPages;
  this.pagesChecked = 0;

  const id = setTimeout(() => {
    console.log(
      '\n=====> TIMEOUT REACHED, STOPPING PAGE GENERATION! Only ' +
        this.pagesChecked +
        ' of ' +
        this.totalPages +
        ' expected pages generated! <===='
    );
    resolveFn();
  }, ttl);

  this.check = function check(key = 'default') {
    this.pagesChecked++;
    console.log(this.pagesChecked, this.totalPages, key);
    if (this.pagesChecked >= this.totalPages) {
      clearTimeout(id);
      resolveFn();
    }
  };
}

function createPages(graphql, createPage, resolve, reject) {
  graphql(`
    {
      allContentfulTemplatePage {
        edges {
          node {
              disclaimer {
              slug
              node_locale
            }
            horeca {
              slug
              node_locale
            }
            error404 {
              slug
              node_locale
            }
            contact {
              slug
              node_locale
            }
            brandCategories {
              slug
              node_locale
            }
            breweryVisit {
              slug
              node_locale
            }
            jobsSingle {
              slug
              node_locale
            }
            jobs {
              slug
              node_locale
            }
            brandCategorySingle {
              slug
              node_locale
            }
            history {
              slug
              node_locale
            }
            brewery {
              slug
              node_locale
            }
            news {
              slug
              node_locale
            }
            brandSingle {
              slug
              node_locale
            }
            singleStory {
              slug
              node_locale
            }
            sitemap {
              slug
              node_locale
            }
            sellingPoints {
              slug
              node_locale
            }
            immo {
              slug
              node_locale
            }
            immoSingle {
              slug
              node_locale
            }
            newsSingle {
              slug
              node_locale
            }
            eventSingle {
              slug
              node_locale
            }
            logos {
              slug
              node_locale
            }
            horecaWiki {
              slug
              node_locale
            }
            bedrijfWiki {
              slug
              node_locale
            }
            breweryProcess {
              slug
              node_locale
            }
            singlePress {
              slug
              node_locale
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      reject(result.errors);
    }
    const numPages = _.reduce(
      result.data.allContentfulTemplatePage.edges,
      (total, languages, lang) => {
        return (
          total +
          _.reduce(
            languages.node,
            (total, pages, pageName) => {
              if (pages && !_.isArray(pages)) {
                console.warn(`Template ${pageName} should be a reference to multiple Slugs!`);
                return total;
              }
              return pages ? total + pages.length : total;
            },
            0
          )
        );
      },
      0
    );

const allPagesCreated = new AllPagesCreated(numPages, resolve);

    _.each(result.data.allContentfulTemplatePage.edges, (edge) => {
      const obj = _.keys(edge.node);
      const firstKey = obj[0];

      const homeTemplate = path.resolve(`./src/templates/home.js`);

      if (edge.node[firstKey]) {
        const language = edge.node[firstKey][0].node_locale;
        console.log(`----> ${language} <----`);
        createPage({
          path: `${language}`,
          component: slash(homeTemplate),
          context: {
            locale: language,
            navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
          },
        });
      }

      _.forEach(edge.node, (value, key) => {
        if (edge.node[key]) {
          const language = edge.node[key][0].node_locale;
          const slug = edge.node[key][0].slug;

          if (key === 'error404') {
            const errorTemplate = path.resolve(`./src/templates/404.js`);
            createPage({
              path: '/404/',
              component: slash(errorTemplate),
              context: {
                locale: 'nl-BE',
                navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
              },
            });
            allPagesCreated.check('404');
            return;
          }

          if (key === 'newsSingle') {
            queries.singleNews(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }

              createSinglePages(
                key,
                createPage,
                result.data.allContentfulNews.edges,
                language,
                slug
              );
              allPagesCreated.check('nieuwsSingle');
            });
            return;
          }
          
          if (key === 'horecaWiki' || key === 'bedrijfWiki') {
            queries.wiki(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              const category = key === 'horecaWiki' ? 'Horeca' : 'Bedrijf';
              createWikiPages(
                key,
                category,
                result.data.allContentfulWikiCategory.edges,
                slug,
                createPage,
                language
              );
              allPagesCreated.check('wikis');
            });
            return;
          }
          if (key === 'singlePress'){
            queries.singlePress(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              createSinglePages(key, createPage, result.data.allContentfulPress.edges, language, slug, 'slug');
              allPagesCreated.check('singlePress');
            });

            return;
          }
          if (key === 'immoSingle') {
            queries.singleImmo(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              createSinglePages(
                key,
                createPage,
                result.data.allContentfulProperty.edges,
                language,
                slug
              );
              allPagesCreated.check('immoSingle');
            });
            return;
          }
          if(key === 'sellingPoints'){
            const template = path.resolve(`./src/templates/${key}.js`);

            storeLocator.getLatLng().then(sellingPoints => {
              queries.singleAbbreviation(graphql)
                .then(result => {
                  if (result.errors){
                    reject(result.errors)
                  }
                  createPage({
                    path: `${language}/${slug}`,
                    component: slash(template),
                    context: {
                      locale: language,
                      navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
                      sellingPoints,
                    },
                  });
                  _.each(result.data.allContentfulAbbreviations.edges, edge => {
                    if(edge.node.slug){
                      createPage({
                        path: `${language}/${slug}/${edge.node.slug}`,
                        component: slash(template),
                        context: {
                          locale: language,
                          id: edge.node.id,
                          navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE' ? '' : `___${language}`}`,
                          sellingPoints,
                        },
                      });
                    }
                  });
                  allPagesCreated.check('sellingPoints');  });
            });
            return;
          }
          if (key === 'logos') {
            queries.logos(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              _.each(edge.node[key], item => {
                createSinglePages(
                  key,
                  createPage,
                  result.data.allContentfulPackshotCategory.edges,
                  language,
                  item.slug
                );
                allPagesCreated.check('logos');
              });
            });
            return;
          }
          if (key === 'singleStory') {
            queries.singleStory(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              createSinglePages(
                key,
                createPage,
                result.data.allContentfulVerhaal.edges,
                language,
                slug
              );
              allPagesCreated.check('singleStory');
            });
            return;
          }
          if (key === 'jobsSingle') {
            queries.singleJob(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              createSinglePages(
                key,
                createPage,
                result.data.allContentfulJob.edges,
                language,
                slug,
                "id"
              );
            });
            queries.extraJobs(graphql).then(result => {
              if (result.errors) {
                reject(result.errors);
              }
              createSinglePages(
                key,
                createPage,
                result.data.allContentfulJobsOther.edges,
                language,
                slug
              );
            });
            allPagesCreated.check('JobsSingle');
            return;
          }
          if (key === 'brandSingle') {
            _.each(edge.node[key], item => {
              const category = _.split(item.slug, '/')[1];

              queries.brandSingle(graphql).then(result => {
                if (result.errors) {
                  reject(result.errors);
                }

                const brandSingleTemplate = path.resolve(`./src/templates/brandSingle.js`);
                const filteredArray = _.filter(result.data.allContentfulMerk.edges, edge => {
                  let slug = _.get(edge.node, 'category.slug');
                  return _.includes(slug, category) && edge.node.node_locale === language;
                });

                _.each(filteredArray, edge => {
                  createPage({
                    path: `${language}/${_.replace(item.slug, ':slug', edge.node.slug)}`,
                    component: slash(brandSingleTemplate),
                    context: {
                      locale: language,
                      id: edge.node.id,
                      navId: `c1DzxdxolMIwGMs2wMucG8W${language === 'nl-BE'
                        ? ''
                        : `___${language}`}`,
                    },
                  });
                });
              });
              allPagesCreated.check('brandSingle');
            });
            return;
          }
          // if (key === 'horeca') {
          //   allPagesCreated.check('horeca');
          //   return;
          // }
          const template = path.resolve(`./src/templates/${key}.js`);
          if (edge.node[key]) {
            _.each(edge.node[key], item => {
              createPage({
                path: `/${item.node_locale}/${item.slug}`,
                component: slash(template),
                context: {
                  locale: item.node_locale,
                  navId: `c1DzxdxolMIwGMs2wMucG8W${item.node_locale === 'nl-BE'
                    ? ''
                    : `___${item.node_locale}`}`,
                 slug: item.slug,
                },
              });

              allPagesCreated.check(key);
            });
          }
        }
      });
    });
  });
}

exports.createPages = ({ graphql, boundActionCreators }) => {
  const { createPage } = boundActionCreators;

  return new Promise((resolve, reject) => {
    createPages(graphql, createPage, resolve, reject);
  });
};

// TODO dynamically create netlify redirect file: https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-plugin-netlify/src/create-redirects.js

exports.modifyWebpackConfig = ({ config, stage }) => {
  if (stage === 'build-html') {
    // Some libraries cannot be server side rendered.
    // More info: https://www.gatsbyjs.org/docs/debugging-html-builds/
    config.loader('null', {
      test: /react-flickity-component|ismobilejs|flickity-bg-lazyload|flatpickr|bowser|react-inview|flickity/,
      loader: 'null-loader',
    });
  }
};

gatsby-browser.js: not changed
gatsby-ssr.js: not changed

Actual result

What happened.

Expected behavior

What should happen?

Steps to reproduce

1.

2.

3.

...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions