Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add way to ignore file during build #25

Closed
KyleAMathews opened this issue Sep 3, 2015 · 10 comments

Comments

Projects
None yet
7 participants
@KyleAMathews
Copy link
Contributor

commented Sep 3, 2015

Perhaps just look for metadata like ignore: true?

E.g. from a markdown file's frontmatter?

@phlogisticfugu

This comment has been minimized.

Copy link
Contributor

commented Sep 4, 2015

isn't this already implemented by using an underscore as the first character in the filename?

@KyleAMathews

This comment has been minimized.

Copy link
Contributor Author

commented Sep 4, 2015

Kinda. That's for template files which are still included but not outputted as html files. This issue is about not including a file at all in the production build. E.g. a draft blog post. Probably this would be implemented by excluding the file when globbing.

@gesposito

This comment has been minimized.

Copy link
Member

commented Sep 15, 2015

Frontmatter has published:
Set to false if you don’t want a specific post to show up when the site is generated.

@KyleAMathews

This comment has been minimized.

Copy link
Contributor Author

commented Feb 18, 2016

Closing this. There's too many ways of doing this to handle it easily within Gatsby. Simple way not to have file built — move it somewhere else!

@abrad45

This comment has been minimized.

Copy link
Contributor

commented Feb 3, 2018

Sorry to dredge up something from nearly two years ago, but I feel that supporting published: false for draft posts is worthwhile. At worst, documentation is outdated:

From https://www.npmjs.com/package/gatsby-transformer-remark:

All frontmatter fields are converted into GraphQL fields.

That's not true, as adding in your own frontmatter fields does not work, nor does published as outlined on https://jekyllrb.com/docs/frontmatter/

@pieh

This comment has been minimized.

Copy link
Contributor

commented Feb 3, 2018

gatsby currently doesn't have any predefined fields in frontmatter so you can add published field but it's up to you to honor that field in your gatsby-node.js.

For example in your createPages function you can modify query that gets markdown nodes from data layer to allMarkdownRemark(filter:{frontmatter:{published:{ne:false}}}) (create pages from markdown that doesn't have published field set to false - so if you don't specify that field, page gets created) or allMarkdownRemark(filter:{frontmatter:{published:{eq:true}}}) (so you would need to specify it to true to create page)

@abrad45

This comment has been minimized.

Copy link
Contributor

commented Feb 11, 2018

@pieh sorry for the delay. Took me a few days to sit down and play with this a bit more. I have this snippet in my gatsby-node.js and every post is returned, even ones with published: false in the frontmatter. I'm wondering if possible frontmatter values are whitelisted or something?

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

    const blogPostTemplate = path.resolve('src/templates/blog.jsx');

    return graphql(`
        {
            allMarkdownRemark(
                sort: { order: DESC, fields: [frontmatter___date] }
                limit: 1000
                filter: { frontmatter: { published: { ne: false } } }
            ) {
                edges {
                    node {
                        html
                        frontmatter {
                            path
                        }
                    }
                }
            }
        }
    `).then(result => {
        if (result.errors) {
            return Promise.reject(result.errors);
        }

        result.data.allMarkdownRemark.edges.forEach(({ node }) => {
            createPage({
                path: node.frontmatter.path,
                component: blogPostTemplate,
            });
        });
    });
};
@abrad45

This comment has been minimized.

Copy link
Contributor

commented Feb 11, 2018

@pieh Aha!

I learned something important about Gatsby tonight :)

The above code worked as you said it would. It prevented pages with published: false in the frontmatter from being rendered. What it did not do is prevent them from appearing on / in the post list, because that data comes from src/pages/index.jsx. I kinda wish that Gatsby had one source of truth that different pages / contexts could draw from (a la redux stores) but I am new to GraphQL, so maybe I'll much prefer this as I get more used to it.

In short, yes this works, and no frontmatter does not have a white list. And, in the case of my blog, I actually want to do the opposite of what I was doing: I'll be making detail pages for draft posts, but not linking to them on the index so I can see how they'll look before I publish them.

Thanks for the help. I appreciate it.

@mtheoryx

This comment has been minimized.

Copy link

commented Apr 7, 2018

I'm doing something similar to what @abrad45 recommended. Except I don't exclude the "draft posts" from my query, I filter them after that promise resolves based on my NODE_ENV.

I want to see all posts in my dev environment, but don't want to generate them when I build the static site for production. Here's my example, if you're curious:

exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`);

  return graphql(`{
    allMarkdownRemark {
      edges {
        node {
          html
          id
          frontmatter {
            title
            date(formatString: "MMMM DD YYYY")
            path
            tags
            excerpt
            published
          }
        }
      }
    }
  }`)
  .then(result => {
    if (result.errors) {
      return Promise.reject(result.errors);
    }

    const allPosts = result.data.allMarkdownRemark.edges;

    const allowedPosts = allPosts.filter(post => 
      (process.env.NODE_ENV === 'development' 
      || post.node.frontmatter.published));

    allowedPosts.forEach(({node}) => {
      createPage({
        path: node.frontmatter.path,
        component: blogPostTemplate
      });
    });
  });
};
@janosh

This comment has been minimized.

Copy link
Contributor

commented Mar 23, 2019

I think when filtering out draft content for the production build, it's best to do it as close to the source as possible. There might be multiple places where draft content shows up on your site and if you don't do the filtering until you've reached gatsby-node's page creation, you would have to implement the filtering in all of these places places individually. For blog posts that might be your blog's index page and/or landing page that displays a list of most recent posts. This leads to verbosity and, if you forget a place, might leak your draft content.

If the content is part of the site's repo, a solution that avoids these problems is to use gatsby-source-filesystem's ignore option. You could add a prefix such as draft- to all files containing draft content and combine that with

{
  resolve: `gatsby-source-filesystem`,
  options: {
    path: `${__dirname}/content`,
    ignore: process.env.NODE_ENV === `production` && [`**/draft-*`]
  }
}

Then, once the content is ready to be published, simply remove the file's draft- prefix and build. An additional advantage to this approach is that it works with both files and folders. If you want to exclude multiple files, simply add the prefix to the parent directory. For example, you could have a permanent drafts folder and move posts or any other type of content in and out of this folder as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.