Skip to content

Instantly share code, notes, and snippets.

@rebotak
Forked from a-barbieri/README.md
Created November 18, 2019 06:26
Show Gist options
  • Select an option

  • Save rebotak/0bc541611b5593bb15de2c7a44a00244 to your computer and use it in GitHub Desktop.

Select an option

Save rebotak/0bc541611b5593bb15de2c7a44a00244 to your computer and use it in GitHub Desktop.

Revisions

  1. @a-barbieri a-barbieri revised this gist Jun 5, 2019. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions server.js
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,7 @@
    const express = require('express');
    const next = require('next');
    const axios = require('axios');
    const fs = require("fs");

    const port = parseInt(process.env.PORT, 10) || 3000;
    const dev = process.env.NODE_ENV !== 'production';
  2. @a-barbieri a-barbieri revised this gist Jun 5, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion sitemap.js
    Original file line number Diff line number Diff line change
    @@ -88,7 +88,7 @@ const createSitemap = () => {
    xml += `${SITE_ROOT}/products/${product.slug}`;
    xml +=
    "</loc><changefreq>always</changefreq><priority>0.5</priority></url>";
    if (product === productList.length - 1) {
    if (index === productList.length - 1) {
    xml += "</urlset>";
    }
    });
  3. @a-barbieri a-barbieri revised this gist Oct 10, 2018. No changes.
  4. @a-barbieri a-barbieri revised this gist Oct 10, 2018. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion server.js
    Original file line number Diff line number Diff line change
    @@ -3,7 +3,6 @@

    const express = require('express');
    const next = require('next');
    const sm = require('sitemap');
    const axios = require('axios');

    const port = parseInt(process.env.PORT, 10) || 3000;
  5. @a-barbieri a-barbieri revised this gist Oct 10, 2018. 2 changed files with 17 additions and 5 deletions.
    20 changes: 16 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -4,12 +4,24 @@

    The current setup has been tested on Next Js `7.0.0`.

    You need to install Axios.

    ```
    $ npm install axios
    ```

    Add a `server.js` and `sitemap.js` files into the root of your NextJs app. If they are already present, update them accordingly.

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE`, `API_SOURCE` and `DESTINATION` in your `.env` file and uncomment `require("dotenv").config();` in `sitemap.js`.
    If you wan you can also install [Dotenv](https://www.npmjs.com/package/dotenv).

    ```
    $ npm install dotenv
    ```

    If you have installed Dotenv you can now set `SITE_ROOT`, `SOURCE`, `API_SOURCE` and `DESTINATION` in your `.env` file and uncomment `require("dotenv").config();` in `sitemap.js`.

    #### IMPORTANT:
    if you haven't set a `SITE_ROOT` and `API_SOURCE` please update `https://example.com` urls in `sitemap.js`.
    if you don't use Dotenv and you haven't set a `SITE_ROOT` and `API_SOURCE` please update `https://example.com` urls in `sitemap.js`.

    ---

    @@ -24,11 +36,11 @@ Your app list some product this way:
    - `http://your.domain/products/product-slug-2`
    - `http://your.domain/products/product-slug-3`

    In the current file we are using a POST request that calls a endpoint `https://your.domain.com/api` to retrieve the product slugs through a query (your will be different). It something like:
    In the current file we are using a POST request that retrieves all products slugs. It something like:

    ```javascript
    axios
    .post(`https://your.domain.com/api`, {
    .post(API_SOURCE, {
    query: `{
    productList: {
    product: {
    2 changes: 1 addition & 1 deletion sitemap.js
    Original file line number Diff line number Diff line change
    @@ -72,7 +72,7 @@ const createSitemap = () => {
    * TODO: Add <lastmod>${lastMod}</lastmod> tag and set priority order
    **/
    return axios
    .post(`https://your.domain.com/api`, {
    .post(API_SOURCE, {
    query: `{
    productList: {
    product: {
  6. @a-barbieri a-barbieri revised this gist Oct 10, 2018. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,8 @@ Add a `server.js` and `sitemap.js` files into the root of your NextJs app. If th

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE`, `API_SOURCE` and `DESTINATION` in your `.env` file and uncomment `require("dotenv").config();` in `sitemap.js`.

    #### IMPORTANT: if you haven't set a `SITE_ROOT` and `API_SOURCE` please update `https://example.com` urls in `sitemap.js`.
    #### IMPORTANT:
    if you haven't set a `SITE_ROOT` and `API_SOURCE` please update `https://example.com` urls in `sitemap.js`.

    ---

  7. @a-barbieri a-barbieri revised this gist Oct 10, 2018. 5 changed files with 189 additions and 68 deletions.
    44 changes: 40 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -4,14 +4,50 @@

    The current setup has been tested on Next Js `7.0.0`.

    Add `buildSitemap.js` and `next.config.js` files into the root of your NextJs app:
    Add a `server.js` and `sitemap.js` files into the root of your NextJs app. If they are already present, update them accordingly.

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE` and `DESTINATION` in your `.env` file and uncomment line 6 of `buildSitemap.js` file.
    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE`, `API_SOURCE` and `DESTINATION` in your `.env` file and uncomment `require("dotenv").config();` in `sitemap.js`.

    #### IMPORTANT: if you haven't set a `SITE_ROOT` please update the url at line 14.
    #### IMPORTANT: if you haven't set a `SITE_ROOT` and `API_SOURCE` please update `https://example.com` urls in `sitemap.js`.

    ---

    ### Dynamic routes

    In case you use dynamic routes in you next.js application you can map them using the `axios` request in `sitemap.js`.

    Example:

    Your app list some product this way:
    - `http://your.domain/products/product-slug-1`
    - `http://your.domain/products/product-slug-2`
    - `http://your.domain/products/product-slug-3`

    In the current file we are using a POST request that calls a endpoint `https://your.domain.com/api` to retrieve the product slugs through a query (your will be different). It something like:

    ```javascript
    axios
    .post(`https://your.domain.com/api`, {
    query: `{
    productList: {
    product: {
    slug
    }
    }
    }`
    })
    .then( /*...*/ )
    .catch( /*...*/ );
    ```

    You need to update also the url following your preferences. See the following line

    ```
    xml += `${SITE_ROOT}/products/${product.slug}`;
    ```

    ---

    ### Build

    In order to create a sitemap, simply run `npm run build` or `yarn build`. A sitemap will be created in `path/to/yourApp/.next/static/sitemap.xml` unless you set a custom `DESTINATION` inyour .env file.
    In order to create a sitemap, simply visit `http://your.domain/sitemap.xml`. A XML file with your sitemap will also be created in `path/to/yourApp/.next/static/sitemap.xml` unless you set a custom `DESTINATION` in your .env file.
    59 changes: 0 additions & 59 deletions buildSitemap.js
    Original file line number Diff line number Diff line change
    @@ -1,59 +0,0 @@
    const path = require("path");
    const glob = require("glob");
    const fs = require("fs");

    // If you use Dotenv you can include your .env variables uncommenting the following line
    // require("dotenv").config();

    // Make sure any symlinks in the project folder are resolved:
    // https://github.com/facebookincubator/create-react-app/issues/637
    const appDirectory = fs.realpathSync(process.cwd());
    const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

    // Update example.com with your domain
    const SITE_ROOT = process.env.SITE_ROOT || "https://example.com";
    // gather all files in pages folder but not the ones starting with `_` (e.g. _document.js and _app.js)
    const SOURCE =
    process.env.SOURCE || path.join(resolveApp("pages"), "/**/!(_*).js");
    const DESTINATION =
    process.env.DESTINATION ||
    path.join(resolveApp(".next/static"), "sitemap.xml");

    if (typeof SITE_ROOT === "undefined") {
    console.error("SITE_ROOT is not defined! Please update your .env file.");
    }

    let diskPages = glob.sync(SOURCE);
    let xml = "";
    xml += '<?xml version="1.0" encoding="UTF-8"?>';
    xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

    diskPages.forEach(page => {
    let stats = fs.statSync(page);
    let modDate = new Date(stats.mtime);
    let lastMod = `${modDate.getFullYear()}-${(
    "0" +
    (modDate.getMonth() + 1)
    ).slice(-2)}-${("0" + modDate.getDate()).slice(-2)}`;

    page = page.replace(resolveApp("pages"), "");
    page = page.replace(/.js$/, "");
    page = `${SITE_ROOT}${page}`;

    if (page.match(/.*\/index$/)) {
    page = page.replace(/(.*)index$/, "$1");
    }

    xml += "<url>";
    xml += `<loc>${page}</loc>`;
    xml += `<lastmod>${lastMod}</lastmod>`;
    xml += `<changefreq>always</changefreq>`;
    xml += `<priority>0.5</priority>`;
    xml += "</url>";
    });

    xml += "</urlset>";

    fs.writeFileSync(DESTINATION, xml);

    console.log(`Wrote sitemap for ${diskPages.length} pages to ${DESTINATION}`);
    5 changes: 0 additions & 5 deletions next.config.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +0,0 @@
    const path = require("path");

    require(path.resolve(__dirname, "buildSitemap"));

    // ... your code
    47 changes: 47 additions & 0 deletions server.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    // @see https://github.com/zeit/next.js/tree/master/examples/custom-server
    // @see https://gist.github.com/edolyne/10bf9cfdd1e75557c3c4c63a2c1fc0b5

    const express = require('express');
    const next = require('next');
    const sm = require('sitemap');
    const axios = require('axios');

    const port = parseInt(process.env.PORT, 10) || 3000;
    const dev = process.env.NODE_ENV !== 'production';
    const app = next({ dev });
    const handle = app.getRequestHandler();

    const { DESTINATION, createSitemap } = require("./sitemap");

    app.prepare()
    .then(() => {
    const server = express();

    // ... some config based on your app

    // This `server.get()` lets you generate a sitemap on the fly and retrive it from http://your.domain/sitemap.xml
    // It also create a file if you need to open it with your editor.
    server.get("/sitemap.xml", function(req, res) {
    res.header("Content-Type", "application/xml");
    (async function sendXML() {
    let xmlFile = await createSitemap();
    // Send it to the browser
    res.send(xmlFile);
    // Create a file on the selected destination
    fs.writeFileSync(DESTINATION, xmlFile);
    })();
    });

    // ... some config based on your app

    // This below is the default config.
    // You might have a different one base on your app based on your app
    server.get('*', (req, res) => {
    const pathname = req.originalUrl.substr(1);
    return handle(req, res)
    });
    server.listen(port, (err) => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${port}`)
    });
    });
    102 changes: 102 additions & 0 deletions sitemap.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    const path = require("path");
    const glob = require("glob");
    const fs = require("fs");
    const axios = require("axios");

    // If you use Dotenv you can include your .env variables uncommenting the following line
    // require("dotenv").config();

    // Make sure any symlinks in the project folder are resolved:
    // https://github.com/facebookincubator/create-react-app/issues/637
    const appDirectory = fs.realpathSync(process.cwd());
    const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

    // SITE_ROOT is the domain of your app
    // Update example.com with your domain or set the env variable
    const SITE_ROOT = process.env.SITE_ROOT || "https://example.com";

    // SOURCE is where are stored all pages files
    // By default it tracks all files in the pages folder
    // without considering the ones starting with `_` (e.g. _document.js and _app.js)
    const SOURCE =
    process.env.SOURCE || path.join(resolveApp("pages"), "/**/!(_*).js");

    // API_SOURCE is the endpoint of you api
    // Update example.com/api with your endpoint or set the env variable
    const API_SOURCE = process.env.API_SOURCE || "https://example.com/api";

    // DESTINATION is where the real file is exported
    // By default is .next/static/sitemap.xml
    const DESTINATION =
    process.env.DESTINATION ||
    path.join(resolveApp(".next/static"), "sitemap.xml");


    const createSitemap = () => {

    /**
    * STEP 1: Store all static pages url
    **/
    let diskPages = glob.sync(SOURCE);
    let xml = "";
    xml += '<?xml version="1.0" encoding="UTF-8"?>';
    xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

    diskPages.forEach(page => {
    let stats = fs.statSync(page);
    let modDate = new Date(stats.mtime);
    let lastMod = `${modDate.getFullYear()}-${(
    "0" +
    (modDate.getMonth() + 1)
    ).slice(-2)}-${("0" + modDate.getDate()).slice(-2)}`;

    page = page.replace(resolveApp("pages"), "");
    page = page.replace(/.js$/, "");
    page = `${SITE_ROOT}${page}`;

    if (page.match(/.*\/index$/)) {
    page = page.replace(/(.*)index$/, "$1");
    }

    xml += "<url>";
    xml += `<loc>${page}</loc>`;
    xml += `<lastmod>${lastMod}</lastmod>`;
    xml += `<changefreq>always</changefreq>`;
    xml += `<priority>0.5</priority>`;
    xml += "</url>";
    });

    /**
    * STEP 2: Store all dynamic pages url
    * In the following snippet we gather all products available
    * TODO: Add <lastmod>${lastMod}</lastmod> tag and set priority order
    **/
    return axios
    .post(`https://your.domain.com/api`, {
    query: `{
    productList: {
    product: {
    slug
    }
    }
    }`
    })
    .then(resp => {
    let { productList } = resp.data;
    productList.forEach((product, index) => {
    xml += "<url><loc>";
    xml += `${SITE_ROOT}/products/${product.slug}`;
    xml +=
    "</loc><changefreq>always</changefreq><priority>0.5</priority></url>";
    if (product === productList.length - 1) {
    xml += "</urlset>";
    }
    });
    return xml;
    })
    .catch(error => {
    console.log(error.message, error.name);
    });
    };

    module.exports = { DESTINATION, createSitemap };
  8. @a-barbieri a-barbieri revised this gist Oct 4, 2018. 2 changed files with 10 additions and 8 deletions.
    16 changes: 9 additions & 7 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,17 @@
    ## Install
    # NextJS sitemap generator

    ### Install

    The current setup has been tested on Next Js `7.0.0`.

    Add the following files to your NextJs app:
    `path/to/yourApp/bin/buildSitemap.js` (bin directory)
    `path/to/yourApp/next.config.js` (root directory)
    Add `buildSitemap.js` and `next.config.js` files into the root of your NextJs app:

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE` and `DESTINATION` in your `.env` file and uncomment line 6 of `buildSitemap.js` file.

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE` and `DESTINATION` in your `.env` file and uncomment line 6 of `bin/buildSitemap.js` file.
    #### IMPORTANT: if you haven't set a `SITE_ROOT` please update the url at line 14.

    ### IMPORTANT: if you haven't set a `SITE_ROOT` please update the url at line 14.
    ---

    ## Build
    ### Build

    In order to create a sitemap, simply run `npm run build` or `yarn build`. A sitemap will be created in `path/to/yourApp/.next/static/sitemap.xml` unless you set a custom `DESTINATION` inyour .env file.
    2 changes: 1 addition & 1 deletion next.config.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    const path = require("path");

    require(path.resolve(__dirname, "./bin/buildSitemap"));
    require(path.resolve(__dirname, "buildSitemap"));

    // ... your code
  9. @a-barbieri a-barbieri created this gist Oct 4, 2018.
    15 changes: 15 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    ## Install

    The current setup has been tested on Next Js `7.0.0`.

    Add the following files to your NextJs app:
    `path/to/yourApp/bin/buildSitemap.js` (bin directory)
    `path/to/yourApp/next.config.js` (root directory)

    If you use [Dotenv](https://www.npmjs.com/package/dotenv) you can set `SITE_ROOT`, `SOURCE` and `DESTINATION` in your `.env` file and uncomment line 6 of `bin/buildSitemap.js` file.

    ### IMPORTANT: if you haven't set a `SITE_ROOT` please update the url at line 14.

    ## Build

    In order to create a sitemap, simply run `npm run build` or `yarn build`. A sitemap will be created in `path/to/yourApp/.next/static/sitemap.xml` unless you set a custom `DESTINATION` inyour .env file.
    59 changes: 59 additions & 0 deletions buildSitemap.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    const path = require("path");
    const glob = require("glob");
    const fs = require("fs");

    // If you use Dotenv you can include your .env variables uncommenting the following line
    // require("dotenv").config();

    // Make sure any symlinks in the project folder are resolved:
    // https://github.com/facebookincubator/create-react-app/issues/637
    const appDirectory = fs.realpathSync(process.cwd());
    const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

    // Update example.com with your domain
    const SITE_ROOT = process.env.SITE_ROOT || "https://example.com";
    // gather all files in pages folder but not the ones starting with `_` (e.g. _document.js and _app.js)
    const SOURCE =
    process.env.SOURCE || path.join(resolveApp("pages"), "/**/!(_*).js");
    const DESTINATION =
    process.env.DESTINATION ||
    path.join(resolveApp(".next/static"), "sitemap.xml");

    if (typeof SITE_ROOT === "undefined") {
    console.error("SITE_ROOT is not defined! Please update your .env file.");
    }

    let diskPages = glob.sync(SOURCE);
    let xml = "";
    xml += '<?xml version="1.0" encoding="UTF-8"?>';
    xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';

    diskPages.forEach(page => {
    let stats = fs.statSync(page);
    let modDate = new Date(stats.mtime);
    let lastMod = `${modDate.getFullYear()}-${(
    "0" +
    (modDate.getMonth() + 1)
    ).slice(-2)}-${("0" + modDate.getDate()).slice(-2)}`;

    page = page.replace(resolveApp("pages"), "");
    page = page.replace(/.js$/, "");
    page = `${SITE_ROOT}${page}`;

    if (page.match(/.*\/index$/)) {
    page = page.replace(/(.*)index$/, "$1");
    }

    xml += "<url>";
    xml += `<loc>${page}</loc>`;
    xml += `<lastmod>${lastMod}</lastmod>`;
    xml += `<changefreq>always</changefreq>`;
    xml += `<priority>0.5</priority>`;
    xml += "</url>";
    });

    xml += "</urlset>";

    fs.writeFileSync(DESTINATION, xml);

    console.log(`Wrote sitemap for ${diskPages.length} pages to ${DESTINATION}`);
    5 changes: 5 additions & 0 deletions next.config.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    const path = require("path");

    require(path.resolve(__dirname, "./bin/buildSitemap"));

    // ... your code