diff --git a/.babel-preset.js b/.babel-preset.js new file mode 100644 index 0000000000000..22e7839689e6d --- /dev/null +++ b/.babel-preset.js @@ -0,0 +1,57 @@ +const r = m => require.resolve(m) + +function preset(context, options = {}) { + const { browser = false, debug = false } = options + const { NODE_ENV, BABEL_ENV } = process.env + + const PRODUCTION = (BABEL_ENV || NODE_ENV) === "production" + + const browserConfig = { + useBuiltIns: false, + targets: { + browsers: PRODUCTION + ? [`last 4 versions`, `safari >= 7`, "ie >= 9"] + : [`last 2 versions`, `not ie <= 11`, `not android 4.4.3`], + }, + } + + const nodeConfig = { + targets: { + node: PRODUCTION ? 6.0 : "current", + }, + } + + return { + presets: [ + [ + r("@babel/preset-env"), + Object.assign( + { + loose: true, + debug: !!debug, + useBuiltIns: "entry", + shippedProposals: true, + modules: "commonjs", + }, + browser ? browserConfig : nodeConfig + ), + ], + [r("@babel/preset-react"), { development: !PRODUCTION }], + r("@babel/preset-flow"), + ], + plugins: [ + r("@babel/plugin-proposal-class-properties"), + r("@babel/plugin-proposal-optional-chaining"), + [ + r("@babel/plugin-transform-runtime"), + { + // we are only polyfilling the node environment + // so we need to enable the runtime replacements for the browser preset + polyfill: !!browser, + }, + ], + ], + } +} + +module.exports = preset diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 91b6bc71e0a86..0000000000000 --- a/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "sourceMaps": true, - "presets": [ - "./.babelrc.js" - ], - "ignore": ["dist"], - "env": { - "production": { - "ignore": ["__tests__", "dist"], - } - }, -} diff --git a/.babelrc.js b/.babelrc.js index 8bdb7b261d848..666c1a0efb70a 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -1,57 +1,15 @@ -const r = m => require.resolve(m) +let ignore = [`**/dist`] -function preset(context, options = {}) { - const { browser = false, debug = false } = options - const { NODE_ENV, BABEL_ENV } = process.env - - const PRODUCTION = (BABEL_ENV || NODE_ENV) === "production" - - const browserConfig = { - useBuiltIns: false, - targets: { - browsers: PRODUCTION - ? [`last 4 versions`, `safari >= 7`, "ie >= 9"] - : [`last 2 versions`, `not ie <= 11`, `not android 4.4.3`], - uglify: PRODUCTION, - }, - } +// Jest needs to compile this code, but generally we don't want this copied +// to output folders +if (process.env.NODE_ENV !== `test`) { + ignore.push(`**/__tests__`) +} - const nodeConfig = { - targets: { - node: PRODUCTION ? 4.0 : "current", - }, - } +const presetAbsPath = require(`path`).join(__dirname, '.babel-preset.js') - return { - presets: [ - [ - r("babel-preset-env"), - Object.assign( - { - loose: true, - debug: !!debug, - useBuiltIns: true, - modules: "commonjs", - }, - browser ? browserConfig : nodeConfig - ), - ], - r("babel-preset-react"), - r("babel-preset-flow"), - ], - plugins: [ - r("babel-plugin-transform-object-rest-spread"), - [ - r("babel-plugin-transform-runtime"), - { - // we are only polyfilling the node environment - // so we need to enable the runtime replacements for the browser preset - polyfill: !!browser, - }, - ], - r(`babel-plugin-transform-flow-strip-types`), - ], - } +module.exports = { + sourceMaps: true, + presets: [presetAbsPath], + ignore, } - -module.exports = preset diff --git a/.flowconfig b/.flowconfig index 75e66a13c27be..5db59cc75f4d7 100644 --- a/.flowconfig +++ b/.flowconfig @@ -4,11 +4,12 @@ [ignore] .*/test/.* .*/node_modules/documentation/.* -.*/node_modules/typography/.* +.*/node_modules/emotion/.* .*/node_modules/fbjs/.* +.*/node_modules/jss/.* +.*/node_modules/preact/.* .*/node_modules/react-side-effect/.* .*/node_modules/styled-components/.* -.*/node_modules/preact/.* -.*/node_modules/jss/.* +.*/node_modules/typography/.* .*/www/.* .*/examples/.* diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index a795bf4692a10..518296b179b6c 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -26,10 +26,10 @@ about: Usage question or discussion about Gatsby. ### Environment (if relevant) -- Gatsby version (`npm list gatsby`): -- gatsby-cli version (`gatsby --version`): -- Node.js version: -- Operating System: + ### File contents (if changed) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..4b00ead876a2d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,12 @@ + diff --git a/.gitignore b/.gitignore index d35570228536c..a63e7f82d5c4b 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ node_modules/ *.sw* .serverless/ +yarn.lock +package-lock.json diff --git a/.travis.yml b/.travis.yml index d9a707362a211..e79c4ef105ca9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,6 @@ jobs: - yarn run bootstrap script: - yarn test - - yarn danger ci - stage: gatsbygram ui tests language: node_js diff --git a/Breaking Changes.md b/Breaking Changes.md new file mode 100644 index 0000000000000..69ed11f48f843 --- /dev/null +++ b/Breaking Changes.md @@ -0,0 +1,12 @@ +- Remove postcss plugins (cssnext, cssimport) from default css loader config +- boundActionCreators => actions +- pathContext => pageContext +- Source & transformer plugins now use UUIDs for ids. If you used glob or regex to query nodes by id then you'll need to query something else. +- Mixed commonjs/es6 modules fail +- Remove explicit polyfill and use the new builtins: usage support in babel 7. +- Changed `modifyBabelrc` to `onCreateBabelConfig` +- Changed `modifyWebpackConfig` to `onCreateWebpackConfig` +- Inlining CSS changed — remove it from any custom html.js as done automatically by core now. +- Manually install `react` and `react-dom`, along with any dependencies required by your plugins. +- Layouts have been removed. To achieve the same behavior as v1, you have to wrap your pages and page templates with your own Layout component. Since Layout is a non-page component, making query has to be done with StaticQuery. +- `graphql` package is exported from `gatsby`. If you use `setFieldsOnGraphQLNodeType` node API, please import graphql types from `gatsby/graphql` to prevent `Schema must contain unique named types but contains multiple types named ""` errors. diff --git a/CHANGELOG.md b/CHANGELOG.md index 284ce8eb86e84..22a68a523cbde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -529,7 +529,7 @@ export const pageQuery = ` } } } -`; +` ``` You must now write: @@ -545,7 +545,7 @@ export const pageQuery = graphql` } } } -`; +` ``` ## [1.0.0-alpha10] - 2016-11-17 diff --git a/README.md b/README.md index 110e4adbc1d3c..98dafa2b14203 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,27 @@ Gatsby -# Gatsby +# Gatsby V2 Beta -⚛️📄🚀 Blazing-fast static site generator for React +⚛️📄🚀 Blazing-fast site generator for React + +**NOTE:** This branch is the beta version of Gatsby V2. You can find documentation at [next.gatsbyjs.org](https://next.gatsbyjs.org/). + +For `gatsby@1`, please see [the v1 branch](https://github.com/gatsbyjs/gatsby/tree/v1). + +**Are you using V1 and want to try upgrading and help prepare Gatsby for v2? Check out [our V1 => V2 migration guide](https://next.gatsbyjs.org//docs/migrating-from-v1-to-v2/).** + +**How are pull requests being handled during the v2 beta?** + +The following policy will be in place during the v2 beta: + +- We will only accept _bug fixes_ for Gatsby v1. Any PRs opened against v1 that are not bug fixes will be closed + +- If the bug fix is applicable to v2, we will open an additional issue to track porting the change to v2 + +- All _new features_ should be opened as pull requests against v2 (the `master` branch) + +We're using this policy as the Gatsby team currently spends a significant amount of time maintaining two active branches - the v1 branch and the v2 branch - we'd like to limit this work to focus on getting v2 released and start working on oft-requested new features like schema snapshots and schema stitching. ## Showcase @@ -235,6 +253,8 @@ Websites built with Gatsby: **[View the docs on gatsbyjs.org](https://www.gatsbyjs.org/docs/)** +[Migrating from v1 to v2?](https://www.gatsbyjs.org/docs/migrating-from-v1-to-v2/) + [Migrating from v0 to v1?](https://www.gatsbyjs.org/docs/migrating-from-v0-to-v1/) [v0 docs](https://github.com/gatsbyjs/gatsby/blob/v0.12.48/docs/index.md) diff --git a/cds-takeaways.md b/cds-takeaways.md new file mode 100644 index 0000000000000..e4f46abf5f5cb --- /dev/null +++ b/cds-takeaways.md @@ -0,0 +1,8 @@ +- preload at top of page for resources ala flipkart +- marketing points — cost of aquisition, boosts from switching + to PWA. +- sites to copy — NASA website + polymer shop but for Packard cars +- On GraphQL errors — print the query plus where it came from and give + them the link to debug it in GraphiQL +- AggressiveSplitPlugin — limit max chunk size to 250kb. +- SW render-dom-stream and stream HTML to browser. diff --git a/dangerfile.js b/dangerfile.js deleted file mode 100644 index 3fa34a6ed849e..0000000000000 --- a/dangerfile.js +++ /dev/null @@ -1,2 +0,0 @@ -// http://danger.systems/js/ -// Danger JS rules go here... diff --git a/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.bkup b/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.bkup deleted file mode 100644 index 3d12fe2a67f3b..0000000000000 --- a/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.bkup +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: "Gatsby 1.0 update" -date: "2017-02-23" -author: "Kyle Mathews" ---- - -*hint — the solution isn't reverting to an idealized "simpler" way of -working on the web* - -*Move problem statement here — that working in JS world feels like riding runaway -train or surfing overly aggressive wave* - -Advanced technologies don't emerge into the world fully grown like -Athena leaping from Zeus' forehead. Instead like babies, they are born -quite helpless and weak and must be slowly nurtured through their -awkward younger years until they are finally productive technology -adults. - -Software technology adoption goes through multiple stages. - -1. R&D / Custom built -2. Productization -3. Commodization - -## R&D and custom built solutions - -The first stage is the time of *R&D and custom built solutions*. -Sophesticated technology groups with advanced needs start running into -problems that existing solutiosn don't solve so feel compelled to build -new technology or cobble together existing tools into novel packages. - -So the Googles, Facebooks, Amazon, Apples of the world are running -applications in containers distributed across dozens of data centers -*years or decades* before Docker and Kubernetes came on the scene. -Similiarly tools like Google Closure Compiler and GWT pioneered advanced -Javascript building and bundling techniquges while the rest of us were -still *manually adding script tags to HTML pages*. - -## Productization - -As time goes on, more and more organizations start to run into the same -problems as these early pioneers and the ideas they pioneered start to -leak out into open source projects. - -These new open source *software products* see rapid adoption from early adopters -and improve quickly. They generate widespread controversy as brash early -adopters loudly market the new tools generating pushback from groups -heavily invested in older tools. - -## Commodization - -As time goes on, more and more of the complexity and sharp edges of the -early-stage product are solved until at last the software product is the -"new normal" which begineers are taught and is taken for granted. - -This is a widely understood pattern and has repeated itself over and -over the past ~60 years since computers came on the scene. - -Microprocessors, operating systems, compilers, databases, the internet, -email all had long awakward adolesants periods where they were seen as -toys or niche tools before growing up to dominate their respective -ecosystems—to the point that we struggle to remember what it was like -before they existed. - -## Adopting new technologies - -Long-lived organizations learn to surf the successive waves of incoming -new technologies by picking points on the technology life cycle to adopt -new tools and techniques. Some need the most advanced technologies and -are vorocious adopters and inventors. Others lag years behind. - -Or as [Erik Meijer summarized -it](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.868&rep=rep1&type=pdf) - -`Change Function = F(Perceived Crisis/Perceived Pain of Adoption)` - -Organizations in rapidly growing industries have many competitors and -are in a constant state of competative crisis so despite high adoption -pain, quickly adopt new technologies. - -Normally this works out nicely for everyone. The pain of developing new -technologies is borne by those that with the greatest need and everyone -else (the vast majority) can wait until things settle down and mature so -adoption is fairly painless. - -## Javascript in crisis - -![Javascript engineering wipes out while attempting to ride the webpack -wave](wipeout.jpg)*Javascript Engineer -wipes out while attempting to ride the webpack wave (from -[vaguelyartistic](https://www.flickr.com/photos/vaguelyartistic/292083492/in/photolist-rP1fh-hKfnhu-dPaHGm-dPaJj7-4Qd1rD-7RpZ8K-bpKqSf-bjWsr-5hAmkk-sfv38A-6T5D58-5KmnwF-oajBZ-8ngHVq-dK6r66-8LbLTj-4SdMxB-bmS9Yg-34wrh2-4kA7U9-dhwznJ-cSaLoq-cdkxFu-4bKzqQ-4C5dd4-FNAdm-4pchw3-pxvVkk-9viJ6k-dh6q21-dh6qiH-afqWxP-r1ftrh-9sjyvY-bz2JCe-7rfMDY-5o29iE-9YHVCe-bCEn8t-agcSdt-5K7ENr-a8aUW-qdyYC-5o27jb-bmS9V4-5nWRWg-tGgt7-hT9qL-9YLQmQ-4ZupJg))* - -* everyone has to build for the web -* tools take a while to mature (the critical path for improving tools -used by 100s of thousands of engineers often goes through surprisingly -few people and they can only work so fast). -* enormous competative pressure — the internet pits everyone against -each other. Dropping one service for another is easy. Everyone has to level -up quickly or get left behind. -* Suggests new tools (React, Webpack, Redux, GraphQL, etc.) *are -actually dramatically better* as sophesticated companies under enormous -competative pressure are rapidly adopting new web tools. - -New tools get widely adopted within *months*(!!!). New Javascript -projects can get 1000s of stars on GitHub within days. Bewilidering -abundance of choices. - -## Riding the runaway Javascript train - -![Javascript engineering riding runaway train](runaway-train.jpg)*Terrified Javascript Engineer riding the runaway Javascript train* - -Highly unsettling for many engineers and organizations. Those most -comfortable being mid to late adopters are forced into becoming early -adopters. - -## Things don't get better until they're made better - -* stay away if you can. Tools are rapidly maturing and consolidating. -* If you can't (you probably can't) — accept building for the web is -much more complex than it used to be. -* Budget more for training and hiring more senior engineers to work on -your web products. -* Invest in open source. They're are many engineers who'd love to work -full-time on open source code. Identify critical tools for your -organization and invest in them. Very high leverage investment as you -gain access to some of the best engineers and the rest of your -engineering organization learns from working with them. - -## As one layer of technology matures, they become the building blocks for the next generation of tools. - -New breed of web tools that take for granted new web technologies. - -Gatsby excemplifies this. Gensis was I wanted easy way to build -really fast websites with all my favorite web tools. Wraps React, -webpack, markdown to make it really easy to build websites out of these -building blocks without any configuration. - -![Javascript engineering masters runaway train](mastered-runaway-train.jpg)*Our hero Javascript Engineers masters the Javascript train* - diff --git a/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.md b/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.md index 0090b425321c4..c823c93d1a964 100644 --- a/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.md +++ b/docs/blog/2017-02-21-1-0-progress-update-where-came-from-where-going/index.md @@ -165,8 +165,8 @@ navigate around, Gatsby loads the JavaScript needed for each route. This means that one page with heavy imports: ```javascript -import d3 from "d3"; -import threejs from "react-threejs"; +import d3 from "d3" +import threejs from "react-threejs" ``` ...won't affect the performance of the rest of the site. @@ -281,23 +281,25 @@ the blog posts. Included with the component is an exported `pageQuery`. ```javascript // A simple React component for rendering a blog page. -import React from "react"; +import React from "react" class BlogPostTemplate extends React.Component { render() { -
-

{this.props.data.markdown.frontmatter.title}

- {this.props.data.markdown.frontmatter.date} -
-
; + return ( +
+

{this.props.data.markdown.frontmatter.title}

+ {this.props.data.markdown.frontmatter.date} +
+
+ ) } } -export default BlogPostTemplate; +export default BlogPostTemplate export const pageQuery = ` query BlogPost($slug: String!) { @@ -311,7 +313,7 @@ export const pageQuery = ` } } } -`; +` ``` All data parsing and processing is plugin-driven. So in time, any imaginable diff --git a/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md b/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md index 955a84266bec5..88e0a8095f85d 100644 --- a/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md +++ b/docs/blog/2017-07-19-creating-a-blog-with-gatsby/index.md @@ -256,15 +256,15 @@ We'll want to create the file `src/templates/blog-post.js` (please create the `src/templates` folder if it does not yet exist!). ```javascript -import React from "react"; -import Helmet from "react-helmet"; +import React from "react" +import Helmet from "react-helmet" // import '../css/blog-post.css'; // make it pretty! export default function Template({ data, // this prop will be injected by the GraphQL query we'll write in a bit }) { - const { markdownRemark: post } = data; // data.markdownRemark holds our post data + const { markdownRemark: post } = data // data.markdownRemark holds our post data return (
@@ -276,7 +276,7 @@ export default function Template({ />
- ); + ) } ``` @@ -378,13 +378,13 @@ Gatsby, as detailed in its [Node API specification][node-spec]. However, we only care about one particular API in this instance, `createPages`. ```javascript -const path = require("path"); +const path = require("path") exports.createPages = ({ boundActionCreators, graphql }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators - const blogPostTemplate = path.resolve(`src/templates/blog-post.js`); -}; + const blogPostTemplate = path.resolve(`src/templates/blog-post.js`) +} ``` Nothing super complex yet! We're using the `createPages` API (which Gatsby will @@ -532,14 +532,14 @@ create `src/pages/tags.js`, the path `http://localhost:8000/tags/` will be available within the browser and the statically generated site. ```javascript -import React from "react"; -import Link from "gatsby-link"; -import Helmet from "react-helmet"; +import React from "react" +import { Link } from "gatsby" +import Helmet from "react-helmet" // import '../css/index.css'; // add some style if you want! export default function Index({ data }) { - const { edges: posts } = data.allMarkdownRemark; + const { edges: posts } = data.allMarkdownRemark return (
{posts @@ -553,10 +553,10 @@ export default function Index({ data }) {

{post.frontmatter.date}

{post.excerpt}

- ); + ) })}
- ); + ) } export const pageQuery = graphql` @@ -575,7 +575,7 @@ export const pageQuery = graphql` } } } -`; +` ``` OK! So we've followed a similar approach to our blog post template, so this @@ -587,7 +587,7 @@ string! GraphQL is awesome. The actual React component is fairly trivial, but one important note should be made. It's important that when linking to internal content, i.e. other blog -links, that you should always use `gatsby-link`. Gatsby does not work if pages +links, that you should always use `Link` from `gatsby`. Gatsby does not work if pages are not routed via this utility. Additionally, this utility also works with `pathPrefix`, which allows for a Gatsby site to be deployed a non-root domain. This is useful if this blog will be hosted on something like GitHub Pages, or diff --git a/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md b/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md index 06fbc2b65bf31..b97f646ee7b31 100644 --- a/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md +++ b/docs/blog/2017-10-01-migrating-my-blog-from-hexo-to-gatsby/index.md @@ -294,16 +294,16 @@ specify a `pageQuery` that will pass data into the default export of that page. ```jsx // src/pages/index.js -import React from "react"; +import React from "react" export default class BlogIndex extends React.Component { render() { // Handle graphql errors if (this.props.errors && this.props.errors.length) { this.props.errors.forEach(({ message }) => { - console.error(`BlogIndex render errr: ${message}`); - }); - return

Errors found: Check the console for details

; + console.error(`BlogIndex render errr: ${message}`) + }) + return

Errors found: Check the console for details

} return ( @@ -313,7 +313,7 @@ export default class BlogIndex extends React.Component { {node.frontmatter.title} ))} - ); + ) } } @@ -329,7 +329,7 @@ export const pageQuery = graphql` } } } -`; +` ``` This is a simplified example, but there are a few things going on that might not @@ -353,7 +353,7 @@ Now let's looks specifically at where we render a link for each blog post: { this.props.data.allMarkdownRemark.edges.map(({ node }, i) => ( {node.frontmatter.title} - )); + )) } ``` @@ -377,7 +377,7 @@ export const pageQuery = graphql` } } } -`; +` ``` This is how you get data from Gatsby into your react components. Make sure you @@ -393,12 +393,12 @@ but the project is still young so the API could change at some point ¯\\_( ツ > But the links don't link anywhere... where's that `href`? -Let's remedy that. Import the `gatsby-link` component and swap it for the simple +Let's remedy that. Import the `Link` component and swap it for the simple `` tag that was in there before: ```jsx import React from 'react'; -import Link from 'gatsby-link'; +import { Link } from 'gatsby'; export default class BlogIndex extends React.Component { render() { @@ -442,7 +442,7 @@ export const pageQuery = graphql` } } } -`; +` ``` ```jsx @@ -451,7 +451,7 @@ export const pageQuery = graphql` {node.frontmatter.title} - )); + )) } ``` @@ -496,15 +496,15 @@ we add custom fields. Example: ```js // gatsby-node.js -const { GraphQLString } = require("graphql"); +const { GraphQLString } = require("gatsby/graphql") const getURL = node => { /* See the source link below for implementation */ -}; +} exports.setFieldsOnGraphQLNodeType = ({ type }) => { if (type.name !== "MarkdownRemark") { - return {}; + return {} } return Promise.resolve({ @@ -512,8 +512,8 @@ exports.setFieldsOnGraphQLNodeType = ({ type }) => { type: GraphQLString, resolve: node => getURL(node), }, - }); -}; + }) +} ``` > Source code for @@ -565,16 +565,16 @@ case, `createPages`. In the same `gatsby-node.js` file as before: // .. other stuff from before... exports.createPages = ({ boundActionCreators }) => { - const { createPage } = boundActionCreators; - const postTemplate = path.resolve("./src/templates/custom-page.js"); + const { createPage } = boundActionCreators + const postTemplate = path.resolve("./src/templates/custom-page.js") // Create a custom page! createPage({ path: `/my-custom-page/`, component: postTemplate, context: {}, // Context will be passed in to the page query as graphql variables - }); -}; + }) +} ``` At the most basic level this method of page creation is quite simple: Grab the @@ -601,8 +601,8 @@ markdownFiles.forEach(post => { context: { id: post.id, }, - }); -}); + }) +}) ``` I've included the pseudo code to highlight the fact that nothing too magical is @@ -619,8 +619,8 @@ work. // NOTE: I'm using async/await to simplify the code since it's now natively supported // in Node 8.x. This means that our function will return a promise exports.createPages = async ({ graphql, boundActionCreators }) => { - const { createPage } = boundActionCreators; - const postTemplate = path.resolve("./src/templates/post.js"); + const { createPage } = boundActionCreators + const postTemplate = path.resolve("./src/templates/post.js") // Using async await. Query will likely be very similar to your pageQuery in index.js const result = await graphql(` @@ -634,11 +634,11 @@ exports.createPages = async ({ graphql, boundActionCreators }) => { } } } - `); + `) if (result.errors) { - console.log(result.errors); - throw new Error("Things broke, see console output above"); + console.log(result.errors) + throw new Error("Things broke, see console output above") } // Create blog posts pages. @@ -650,9 +650,9 @@ exports.createPages = async ({ graphql, boundActionCreators }) => { // Context will be passed in to the page query as graphql vars id: node.id, }, - }); - }); -}; + }) + }) +} ``` Notice that the query is very similar to the `pageQuery` in index.js but it's @@ -672,11 +672,11 @@ Here it is in all it's glory: ```jsx // src/templates/post.js -import React from "react"; +import React from "react" export default class BlogPost extends React.Component { render() { - const post = this.props.data.markdownRemark; + const post = this.props.data.markdownRemark return (
@@ -686,7 +686,7 @@ export default class BlogPost extends React.Component { className="content" />
- ); + ) } } @@ -700,7 +700,7 @@ export const pageQuery = graphql` html } } -`; +` ``` If you're not used to GraphQL syntax the `pageQuery` might be a little diff --git a/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md b/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md index 5ace5c46cf69a..b5756b28e1635 100644 --- a/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md +++ b/docs/blog/2017-10-05-portfolio-site-gatsby-wordpress/index.md @@ -82,7 +82,7 @@ export const projectsPageQuery = graphql` } } } -`; +` ``` Pulling blog posts was even easier! If you’d like to sort them by date, ID, @@ -104,7 +104,7 @@ export const postQuery = graphql` } } } -`; +` ``` ## Wrap up and future diff --git a/docs/blog/2017-10-16-making-website-building-fun/index.md b/docs/blog/2017-10-16-making-website-building-fun/index.md index d1a1ec45ead66..dd54a462b7744 100644 --- a/docs/blog/2017-10-16-making-website-building-fun/index.md +++ b/docs/blog/2017-10-16-making-website-building-fun/index.md @@ -21,14 +21,14 @@ simple I realized you almost don't need documentation. A React header component using it would look like this: ```jsx -import React from "react"; -import Headroom from "react-headroom"; +import React from "react" +import Headroom from "react-headroom" export default () => (

You can put anything you'd like inside the Headroom Component

-); +) ``` Having coming from years of building things with Backbone.js and jQuery where @@ -50,11 +50,11 @@ Compare this with the minimum code necessary for the original headroom.js. ```js // grab the element -var myElement = document.querySelector("header"); +var myElement = document.querySelector("header") // construct an instance of Headroom, passing the element -var headroom = new Headroom(myElement); +var headroom = new Headroom(myElement) // initialise -headroom.init(); +headroom.init() ``` #### CSS @@ -203,15 +203,15 @@ Here's what a really simple Gatsby page component using gatsby-image would look like: ```jsx -import React from "react"; -import Img from "gatsby-image"; +import React from "react" +import Img from "gatsby-image" export default ({ data }) => (

Hello gatsby-image

- +
-); +) ``` So this is all very nice and it's far better to be able to use this from NPM vs. @@ -249,21 +249,21 @@ The code I showed above was missing the GraphQL query. A full image component would look like: ```jsx -import React from "react"; -import Img from "gatsby-image"; +import React from "react" +import Img from "gatsby-image" export default ({ data }) => (

Hello gatsby-image

- +
-); +) export const query = graphql` query GatsbyImageSampleQuery { file(relativePath: { eq: "images/an-image.jpeg" }) { childImageSharp { - resolutions(width: l25, height: 125) { + fixed(width: l25, height: 125) { src srcSet width @@ -272,7 +272,7 @@ export const query = graphql` } } } -`; +` ``` So instead of a long pipeline of tasks to setup optimized images for your site, diff --git a/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md b/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md index 89c5e3693affb..597c1a76f3721 100644 --- a/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md +++ b/docs/blog/2017-10-17-building-i18n-with-gatsby/index.md @@ -84,10 +84,10 @@ but copied here for convenience. You'll need to create an i18n component and import it somewhere (we did it in our index layout): ```jsx -import i18n from "i18next"; -import Backend from "i18next-xhr-backend"; -import LanguageDetector from "i18next-browser-languagedetector"; -import { reactI18nextModule } from "react-i18next"; +import i18n from "i18next" +import Backend from "i18next-xhr-backend" +import LanguageDetector from "i18next-browser-languagedetector" +import { reactI18nextModule } from "react-i18next" i18n .use(Backend) @@ -109,9 +109,9 @@ i18n react: { wait: true, }, - }); + }) -export default i18n; +export default i18n ``` ## Locales @@ -164,16 +164,16 @@ little hook to our `gatsby-node.js` file. It copies the locales folder post build and gets everything in the right place: ```javascript -const fs = require("fs-extra"); -const path = require("path"); +const fs = require("fs-extra") +const path = require("path") exports.onPostBuild = () => { - console.log("Copying locales"); + console.log("Copying locales") fs.copySync( path.join(__dirname, "/src/locales"), path.join(__dirname, "/public/locales") - ); -}; + ) +} ``` ## Using with a component @@ -185,23 +185,23 @@ React-i18next uses a HOC to wrap your component and provide some props to handle language switching. Here's our `PageHeader` component: ```jsx -import React, { Component } from "react"; -import { translate } from "react-i18next"; +import React, { Component } from "react" +import { translate } from "react-i18next" class PageHeader extends Component { render() { - const { t } = this.props; + const { t } = this.props return (

{t("heading")}

{t("description")}

- ); + ) } } -export default translate("PageHeader")(PageHeader); +export default translate("PageHeader")(PageHeader) ``` Pretty simple! The string provided to `translate` is the corresponding JSON file @@ -226,32 +226,32 @@ Finally, to make it easy for our users to switch language we need to create a little component. Here's an example from our site: ```jsx -import React, { Component } from "react"; -import classNames from "classnames"; -import { translate } from "react-i18next"; +import React, { Component } from "react" +import classNames from "classnames" +import { translate } from "react-i18next" class LanguageSwitcher extends Component { constructor(props) { - super(props); - const { i18n } = this.props; - this.state = { language: i18n.language }; + super(props) + const { i18n } = this.props + this.state = { language: i18n.language } - this.handleChangeLanguage = this.handleChangeLanguage.bind(this); + this.handleChangeLanguage = this.handleChangeLanguage.bind(this) } componentWillReceiveProps(nextProps) { - this.setState({ language: nextProps.i18n.language }); + this.setState({ language: nextProps.i18n.language }) } handleChangeLanguage(lng) { - const { i18n } = this.props; - i18n.changeLanguage(lng); + const { i18n } = this.props + i18n.changeLanguage(lng) } renderLanguageChoice({ code, label }) { const buttonClass = classNames("LanguageSwitcher__button", { "LanguageSwitcher__button--selected": this.state.language === code, - }); + }) return ( - ); + ) } render() { const languages = [ { code: "en", label: "English" }, { code: "cy", label: "Cymraeg" }, - ]; + ] return (
{languages.map(language => this.renderLanguageChoice(language))}
- ); + ) } } -export default translate("LanguageSwitcher")(LanguageSwitcher); +export default translate("LanguageSwitcher")(LanguageSwitcher) ``` This is a pretty simple component. We're setting the `language` state based on @@ -298,22 +298,22 @@ To let it render the content into html, you need to load i18n namespaces (using ```js // gatsby-ssr.js -import React from "react"; -import { Provider } from "react-redux"; -import { renderToString } from "react-dom/server"; -import i18n from "./src/i18n"; +import React from "react" +import { Provider } from "react-redux" +import { renderToString } from "react-dom/server" +import i18n from "./src/i18n" -import createStore from "./src/state/createStore"; +import createStore from "./src/state/createStore" exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => { i18n.loadNamespaces(["common"], () => { - const store = createStore(); + const store = createStore() const ConnectedBody = () => ( {bodyComponent} - ); - replaceBodyHTMLString(renderToString()); - }); -}; + ) + replaceBodyHTMLString(renderToString()) + }) +} ``` ### Without redux @@ -323,17 +323,17 @@ exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => { ```js // gatsby-ssr.js -import React from "react"; -import { renderToString } from "react-dom/server"; -import i18n from "./src/i18n"; +import React from "react" +import { renderToString } from "react-dom/server" +import i18n from "./src/i18n" -import createStore from "./src/state/createStore"; +import createStore from "./src/state/createStore" exports.replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => { i18n.loadNamespaces(["common"], () => { - replaceBodyHTMLString(bodyComponent); - }); -}; + replaceBodyHTMLString(bodyComponent) + }) +} ``` > `translate` hoc from react-i18next cause page / component not able to SSR. I make it works by import i18n & use i18n.t diff --git a/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md b/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md index 5d6ced8afb252..a5d9588e28669 100644 --- a/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md +++ b/docs/blog/2017-10-20-from-wordpress-to-developing-in-react-starting-to-see-it/index.md @@ -53,17 +53,17 @@ makes groking easier. I have my layout, template and config modules at hand in the folder structure, without duplication. ```js -import React from "react"; +import React from "react" // Template for blog page export default ({ data }) => { - const post = data.markdownRemark; + const post = data.markdownRemark return (

{post.frontmatter.title}

- ); -}; + ) +} // The data query export const query = graphql` query BlogPostQuery($slug: String!) { @@ -75,7 +75,7 @@ export const query = graphql` } } } -`; +` ``` Whilst this might _look_ weird, it actually makes it much easier to understand @@ -112,7 +112,7 @@ export const query = graphql` } } } -`; +` ``` Aside from those pesky tick characters, which are sometimes hard to spot for a diff --git a/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md b/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md index d847b69394a9e..f5b857147056d 100644 --- a/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md +++ b/docs/blog/2017-11-06-migrate-hugo-gatsby/index.md @@ -99,7 +99,7 @@ This might sound way more complicated than what it is: ```jsx exports.createPages = ({ graphql, boundActionCreators }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators graphql(` { allMarkdownRemark { @@ -115,10 +115,10 @@ exports.createPages = ({ graphql, boundActionCreators }) => { } } `).then(result => { - const posts = result.data.allMarkdownRemark.edges; + const posts = result.data.allMarkdownRemark.edges // Create content programatically here - }); -}; + }) +} ``` As you see, getting the list of posts can be done in a single query. @@ -128,10 +128,10 @@ prefer to keep in a separate module. For example, creating posts works like following: ```jsx -const path = require(`path`); +const path = require(`path`) module.exports = (createPage, nodes) => { - const template = path.resolve(`src/templates/post.js`); + const template = path.resolve(`src/templates/post.js`) nodes.map(({ node }) => { if (node.frontmatter.slug) { @@ -141,10 +141,10 @@ module.exports = (createPage, nodes) => { context: { slug: node.frontmatter.slug, }, - }); + }) } - }); -}; + }) +} ``` I re-use the `slug` field of the frontmatter of my existing structure. I don't @@ -234,12 +234,12 @@ both tags and pagination scenarios. I kept them as separate action creators and I just called them in the main creator function like this: ```jsx -const createPostPages = require(`./gatsby-actions/createPostPages`); -const createPaginatedPostsPages = require(`./gatsby-actions/createPaginatedPostsPages`); -const createTagPages = require(`./gatsby-actions/createTagPages`); +const createPostPages = require(`./gatsby-actions/createPostPages`) +const createPaginatedPostsPages = require(`./gatsby-actions/createPaginatedPostsPages`) +const createTagPages = require(`./gatsby-actions/createTagPages`) exports.createPages = ({ graphql, boundActionCreators }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators graphql(` { allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { @@ -255,41 +255,41 @@ exports.createPages = ({ graphql, boundActionCreators }) => { } } `).then(result => { - const posts = result.data.allMarkdownRemark.edges; - createPostPages(createPage, posts); - createPaginatedPostsPages(createPage, posts); - createTagPages(createPage, posts); - }); -}; + const posts = result.data.allMarkdownRemark.edges + createPostPages(createPage, posts) + createPaginatedPostsPages(createPage, posts) + createTagPages(createPage, posts) + }) +} ``` Easy to read, understand and mantain. The pagination module is a bit longer than the one of the posts: ```jsx -const path = require(`path`); +const path = require(`path`) module.exports = (createPage, nodes) => { - const template = path.resolve(`src/templates/postList.js`); - const paginateSize = 10; + const template = path.resolve(`src/templates/postList.js`) + const paginateSize = 10 // Split posts into arrays of length equal to number posts on each page/paginateSize const groupedPages = nodes .map((node, index) => { return index % paginateSize === 0 ? nodes.slice(index, index + paginateSize) - : null; + : null }) - .filter(item => item); + .filter(item => item) // Create new indexed route for each array groupedPages.forEach((group, index, groups) => { - const pageIndex = index === 0 ? `` : index + 1; - const paginationRoute = `/blog/${pageIndex}`; + const pageIndex = index === 0 ? `` : index + 1 + const paginationRoute = `/blog/${pageIndex}` // Avoid showing `Previous` link on first page - passed to context - const first = index === 0 ? true : false; + const first = index === 0 ? true : false // Avoid showing `Next` link if this is the last page - passed to context - const last = index === groups.length - 1 ? true : false; + const last = index === groups.length - 1 ? true : false return createPage({ path: paginationRoute, @@ -300,9 +300,9 @@ module.exports = (createPage, nodes) => { last, index: index + 1, }, - }); - }); -}; + }) + }) +} ``` Then, pull context information in the React component: @@ -359,7 +359,7 @@ createPage({ context: { posts, }, -}); +}) ``` For the inner tag page: @@ -373,7 +373,7 @@ createPage({ post, tag: tagName, }, -}); +}) ``` ### Admin panel @@ -426,8 +426,8 @@ This is my admin page React component which is placed in `src/pages/admin` so that Gatsby delivers the HTML page at `/admin`. ```jsx -import React from "react"; -import Helmet from "react-helmet"; +import React from "react" +import Helmet from "react-helmet" const AdminPage = () => (
@@ -447,9 +447,9 @@ const AdminPage = () => ( />
-); +) -export default AdminPage; +export default AdminPage ``` In order for NetlifyCMS script to find the configuration file correctly, diff --git a/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md b/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md index 9586bc49f1916..87a10420146b0 100644 --- a/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md +++ b/docs/blog/2017-11-08-migrate-from-jekyll-to-gatsby/index.md @@ -45,7 +45,7 @@ matter block, so you don't have to change anything. You just need to install Then, in your `gatsby-config.js` file add: ```js -plugins: ["gatsby-transformer-remark"]; +plugins: ["gatsby-transformer-remark"] ``` ### Theme @@ -89,30 +89,30 @@ extension API to tweak the slug: ```js exports.onCreateNode = ({ node, getNode, boundActionCreators }) => { - const { createNodeField } = boundActionCreators; + const { createNodeField } = boundActionCreators if (node.internal.type === `MarkdownRemark`) { - const { categories } = node.frontmatter; + const { categories } = node.frontmatter - const filename = createFilePath({ node, getNode, basePath: `pages` }); + const filename = createFilePath({ node, getNode, basePath: `pages` }) // get the date and title from the file name const [, date, title] = filename.match( /^\/([\d]{4}-[\d]{2}-[\d]{2})-{1}(.+)\/$/ - ); + ) // create a new slug concatenating everything const slug = `/${slugify( categories.concat([date]).join("-"), "/" - )}/${title}/`; + )}/${title}/` - createNodeField({ node, name: `slug`, value: slug }); + createNodeField({ node, name: `slug`, value: slug }) // save the date for later use - createNodeField({ node, name: `date`, value: date }); + createNodeField({ node, name: `date`, value: date }) } -}; +} ``` ### Deploy diff --git a/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md b/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md index 55c5a01817ca1..73a83df2caaca 100644 --- a/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md +++ b/docs/blog/2017-12-07-taking-gatsby-for-a-spin/index.md @@ -64,7 +64,7 @@ export const query = graphql` date(formatString: "DD MMMM, YYYY") cover { childImageSharp { - resolutions(width: 1200) { + fixed(width: 1200) { src } } @@ -72,7 +72,7 @@ export const query = graphql` } } } -`; +` ``` ### Deployment and content management can be so good! diff --git a/docs/blog/2018-01-22-getting-started-gatsby-and-wordpress/index.md b/docs/blog/2018-01-22-getting-started-gatsby-and-wordpress/index.md index 3c3cbbaccf3fd..0e5f147481179 100644 --- a/docs/blog/2018-01-22-getting-started-gatsby-and-wordpress/index.md +++ b/docs/blog/2018-01-22-getting-started-gatsby-and-wordpress/index.md @@ -29,7 +29,7 @@ module.exports = { title: "Gatsby Default Starter", }, plugins: ["gatsby-plugin-react-helmet"], -}; +} ``` See the [docs page on gatsby-config.js](/docs/gatsby-config/) for more. @@ -95,7 +95,7 @@ I used the `gatsby-node.js` file from the plugin demo to get started. For my pur For example, below is the part of the demo `gatsby-node.js` file that iterates over all the WordPress post data. ```javascript -const postTemplate = path.resolve(`./src/templates/post.js`); +const postTemplate = path.resolve(`./src/templates/post.js`) _.each(result.data.allWordpressPost.edges, edge => { createPage({ @@ -108,8 +108,8 @@ _.each(result.data.allWordpressPost.edges, edge => { context: { id: edge.node.id, }, - }); -}); + }) +}) ``` The [docs define a Gatsby page](/docs/api-specification/#concepts) as "a site page with a pathname, a template component, and optional graphql query and layout component." See the docs on the [createPage bound action creator](/docs/bound-action-creators/#createPage) and [guide on creating and modifying pages for more detail](/docs/creating-and-modifying-pages/). diff --git a/docs/blog/2018-06-07-build-a-gatsby-blog-using-the-cosmic-js-source-plugin/index.md b/docs/blog/2018-06-07-build-a-gatsby-blog-using-the-cosmic-js-source-plugin/index.md index 4a7d9fa7f25c6..4595007104e15 100644 --- a/docs/blog/2018-06-07-build-a-gatsby-blog-using-the-cosmic-js-source-plugin/index.md +++ b/docs/blog/2018-06-07-build-a-gatsby-blog-using-the-cosmic-js-source-plugin/index.md @@ -119,29 +119,29 @@ Now restart the server to apply the updates. First, we want to display the list of posts on the homepage. To do so, add the following content to `src/pages/index.js`: ```javascript -import React from "react"; -import Link from "gatsby-link"; -import get from "lodash/get"; -import Helmet from "react-helmet"; +import React from "react" +import Link from "gatsby-link" +import get from "lodash/get" +import Helmet from "react-helmet" -import Bio from "../components/Bio"; -import { rhythm } from "../utils/typography"; +import Bio from "../components/Bio" +import { rhythm } from "../utils/typography" class BlogIndex extends React.Component { render() { const siteTitle = get( this, "props.data.cosmicjsSettings.metadata.site_title" - ); - const posts = get(this, "props.data.allCosmicjsPosts.edges"); - const author = get(this, "props.data.cosmicjsSettings.metadata"); + ) + const posts = get(this, "props.data.allCosmicjsPosts.edges") + const author = get(this, "props.data.cosmicjsSettings.metadata") return (
{posts.map(({ node }) => { - const title = get(node, "title") || node.slug; + const title = get(node, "title") || node.slug return (

@@ -361,20 +361,20 @@ That looks fine, but at this point, Gatsby does not know when this template shou Path: `gatsby-node.js` ```javascript -const _ = require("lodash"); -const Promise = require("bluebird"); -const path = require("path"); +const _ = require("lodash") +const Promise = require("bluebird") +const path = require("path") exports.createPages = ({ graphql, boundActionCreators }) => { - const { createPage } = boundActionCreators; - const indexPage = path.resolve("./src/pages/index.js"); + const { createPage } = boundActionCreators + const indexPage = path.resolve("./src/pages/index.js") createPage({ path: `posts`, component: indexPage, }); return new Promise((resolve, reject) => { - const blogPost = path.resolve("./src/templates/blog-post.js"); + const blogPost = path.resolve("./src/templates/blog-post.js") resolve( graphql( ` @@ -399,12 +399,11 @@ exports.createPages = ({ graphql, boundActionCreators }) => { } // Create blog posts pages. - const posts = result.data.allCosmicjsPosts.edges; + const posts = result.data.allCosmicjsPosts.edges _.each(posts, (post, index) => { - const next = - index === posts.length - 1 ? null : posts[index + 1].node; - const previous = index === 0 ? null : posts[index - 1].node; + const next = index === posts.length - 1 ? null : posts[index + 1].node + const previous = index === 0 ? null : posts[index - 1].node createPage({ path: `posts/${post.node.slug}`, diff --git a/docs/blog/2018-1-18-strapi-and-gatsby/index.md b/docs/blog/2018-1-18-strapi-and-gatsby/index.md index c101ee570c283..deaf2f9e039ed 100644 --- a/docs/blog/2018-1-18-strapi-and-gatsby/index.md +++ b/docs/blog/2018-1-18-strapi-and-gatsby/index.md @@ -200,7 +200,7 @@ module.exports = { }, }, ], -}; +} ``` Then, restart the server to let Gatsby consider these updates. @@ -212,8 +212,8 @@ First, we want to display the list of articles. To do so, add the following cont _Path: `src/pages/index.js`_ ```jsx -import React from "react"; -import Link from "gatsby-link"; +import React from "react" +import { Link } from "gatsby" const IndexPage = ({ data }) => (
@@ -232,9 +232,9 @@ const IndexPage = ({ data }) => ( Go to page 2
-); +) -export default IndexPage; +export default IndexPage export const pageQuery = graphql` query IndexQuery { @@ -248,7 +248,7 @@ export const pageQuery = graphql` } } } -`; +` ``` #### What are we doing here? @@ -272,8 +272,8 @@ Let's create the template, containing a specific GraphQL request and defining th _Path: `src/templates/article.js`_ ```jsx -import React from "react"; -import Link from "gatsby-link"; +import React from "react" +import { Link } from "gatsby" const ArticleTemplate = ({ data }) => (
@@ -286,9 +286,9 @@ const ArticleTemplate = ({ data }) => (

{data.strapiArticle.content}

-); +) -export default ArticleTemplate; +export default ArticleTemplate export const query = graphql` query ArticleTemplate($id: String!) { @@ -301,7 +301,7 @@ export const query = graphql` } } } -`; +` ``` That looks fine, but at this point, Gatsby does not know when this template should be displayed. Each article needs a specific URL. So, we are going to inform Gatsby about the new URLs we need thanks to the [`createPage` function](https://www.gatsbyjs.org/docs/creating-and-modifying-pages). @@ -311,7 +311,7 @@ First, we are going to code a new function called `makeRequest` to execute the G _Path: `gatsby-node.js`_ ```jsx -const path = require(`path`); +const path = require(`path`) const makeRequest = (graphql, request) => new Promise((resolve, reject) => { @@ -319,18 +319,18 @@ const makeRequest = (graphql, request) => resolve( graphql(request).then(result => { if (result.errors) { - reject(result.errors); + reject(result.errors) } - return result; + return result }) - ); - }); + ) + }) // Implement the Gatsby API “createPages”. This is called once the // data layer is bootstrapped to let plugins create pages from data. exports.createPages = ({ boundActionCreators, graphql }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators const getArticles = makeRequest( graphql, @@ -354,13 +354,13 @@ exports.createPages = ({ boundActionCreators, graphql }) => { context: { id: node.id, }, - }); - }); - }); + }) + }) + }) // Query for articles nodes to use in creating pages. - return getArticles; -}; + return getArticles +} ``` Restart the Gatsby server. @@ -378,8 +378,8 @@ The processes for creating author views and article pages are very similar. Firs _Path: `src/templates/user.js`_ ```jsx -import React from "react"; -import Link from "gatsby-link"; +import React from "react" +import { Link } from "gatsby" const UserTemplate = ({ data }) => (
@@ -395,9 +395,9 @@ const UserTemplate = ({ data }) => ( ))}
-); +) -export default UserTemplate; +export default UserTemplate export const query = graphql` query UserTemplate($id: String!) { @@ -411,7 +411,7 @@ export const query = graphql` } } } -`; +` ``` Second, we update the `gatsby-node.js` file to create the URLs: @@ -419,7 +419,7 @@ Second, we update the `gatsby-node.js` file to create the URLs: _Path: `gatsby-node.js`_ ```jsx -const path = require(`path`); +const path = require(`path`) const makeRequest = (graphql, request) => new Promise((resolve, reject) => { @@ -427,18 +427,18 @@ const makeRequest = (graphql, request) => resolve( graphql(request).then(result => { if (result.errors) { - reject(result.errors); + reject(result.errors) } - return result; + return result }) - ); - }); + ) + }) // Implement the Gatsby API “createPages”. This is called once the // data layer is bootstrapped to let plugins create pages from data. exports.createPages = ({ boundActionCreators, graphql }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators const getArticles = makeRequest( graphql, @@ -462,9 +462,9 @@ exports.createPages = ({ boundActionCreators, graphql }) => { context: { id: node.id, }, - }); - }); - }); + }) + }) + }) const getAuthors = makeRequest( graphql, @@ -488,13 +488,13 @@ exports.createPages = ({ boundActionCreators, graphql }) => { context: { id: node.id, }, - }); - }); - }); + }) + }) + }) // Queries for articles and authors nodes to use in creating pages. - return Promise.all([getArticles, getAuthors]); -}; + return Promise.all([getArticles, getAuthors]) +} ``` Finally, restart the server and visit the author page from the article view's links. diff --git a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md index 95a447a4c0189..de5d10c68bbf7 100644 --- a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md +++ b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md @@ -80,7 +80,7 @@ module.exports = { `gatsby-transformer-sharp`, `gatsby-plugin-sharp`, ], -}; +} ``` ## Creating pages and GraphQL queries @@ -115,14 +115,14 @@ Here is one of the first pages I rendered into a table format: Here are more examples of pages I created. This is the photo gallery page: ```jsx -import React from "react"; +import React from "react" export default ({ data }) => { - console.log(data); + console.log(data) // The next line is where the code drills deeper into the data structure to finally get to photos. // In order to create the correct order here, follow the structure of the GraphQL query. - const photos = data.allContentfulPhotoGallery.edges[0].node.photos; - console.log(photos); + const photos = data.allContentfulPhotoGallery.edges[0].node.photos + console.log(photos) return (
@@ -141,8 +141,8 @@ export default ({ data }) => {
))}

- ); -}; + ) +} export const query = graphql` query PhotoQuery { @@ -159,7 +159,7 @@ query PhotoQuery { } } } - }`; + }` ``` ## More complex pages @@ -169,12 +169,12 @@ The list of Tricks & Commands presented a complex challenge because not all entr Because each entry was inconsistent, my friends helped me figure out a way to use JS to make sure we only requested a photo to be printed IF the photo existed. And if a particular entry didn't have a photo, the computer could forgive it (just this once). Here is the code from that page: ```jsx -import React from "react"; +import React from "react" export default ({ data }) => { - const tricks = data.allContentfulTricksCommands.edges; - console.log(tricks); - console.log(data); + const tricks = data.allContentfulTricksCommands.edges + console.log(tricks) + console.log(data) return (
@@ -198,8 +198,8 @@ export default ({ data }) => {
))}
- ); -}; + ) +} export const query = graphql` query CommandsQuery { @@ -224,7 +224,7 @@ export const query = graphql` } } } -`; +` ``` ## Final thoughts diff --git a/docs/blog/2018-2-27-why-i-upgraded-my-website-to-gatsbyjs-from-jekyll/index.md b/docs/blog/2018-2-27-why-i-upgraded-my-website-to-gatsbyjs-from-jekyll/index.md index be38ae3ab9388..4e2d436727ba8 100644 --- a/docs/blog/2018-2-27-why-i-upgraded-my-website-to-gatsbyjs-from-jekyll/index.md +++ b/docs/blog/2018-2-27-why-i-upgraded-my-website-to-gatsbyjs-from-jekyll/index.md @@ -51,7 +51,7 @@ For example, I defined a `PostTemplate` which will be used to render pages for a ```jsx // src/templates/Post.jsx -import React from "react"; +import React from "react" export default function PostTemplate({ data: { @@ -67,7 +67,7 @@ export default function PostTemplate({ {date}
- ); + ) } export const pageQuery = graphql` @@ -80,7 +80,7 @@ export const pageQuery = graphql` } } } -`; +` ``` When the `` component needs to be rendered into a page, the accompanying exported `pageQuery`, a GraphQL query is made, and the results are passed in as props into the component. diff --git a/docs/blog/gatsby-v1.md b/docs/blog/gatsby-v1.md index 2e6162c085f20..5f9d05cf08061 100644 --- a/docs/blog/gatsby-v1.md +++ b/docs/blog/gatsby-v1.md @@ -162,7 +162,7 @@ the blog posts. Included with the component is an exported `pageQuery`. ```jsx // A basic React component for rendering a blog page. -import React from "react"; +import React from "react" class BlogPostTemplate extends React.Component { render() { @@ -176,11 +176,11 @@ class BlogPostTemplate extends React.Component { }} />
- ); + ) } } -export default BlogPostTemplate; +export default BlogPostTemplate export const pageQuery = graphql` query BlogPost($slug: String!) { @@ -194,7 +194,7 @@ export const pageQuery = graphql` } } } -`; +` ``` All data sourcing and transforming is plugin-driven. So in time, any imaginable @@ -276,8 +276,8 @@ you navigate around, Gatsby loads in the code needed for each route. This means that one page with heavy imports: ```javascript -import d3 from "d3"; -import threejs from "react-threejs"; +import d3 from "d3" +import threejs from "react-threejs" ``` ...won't affect the performance of the rest of the site. diff --git a/docs/blog/gatsbygram-case-study/index.md b/docs/blog/gatsbygram-case-study/index.md index b79aaa7a8ec48..79fbd94d4365b 100644 --- a/docs/blog/gatsbygram-case-study/index.md +++ b/docs/blog/gatsbygram-case-study/index.md @@ -149,18 +149,18 @@ the site's [`gatsby-node.js` file](https://github.com/gatsbyjs/gatsby/blob/master/examples/gatsbygram/gatsby-node.js): ```javascript -const _ = require(`lodash`); -const Promise = require(`bluebird`); -const path = require(`path`); -const slug = require(`slug`); -const slash = require(`slash`); +const _ = require(`lodash`) +const Promise = require(`bluebird`) +const path = require(`path`) +const slug = require(`slug`) +const slash = require(`slash`) // Implement the Gatsby API “createPages”. This is // called after the Gatsby bootstrap is finished so you have // access to any information necessary to programmatically // create pages. exports.createPages = ({ graphql, boundActionCreators }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators return new Promise((resolve, reject) => { // The “graphql” function allows us to run arbitrary @@ -188,11 +188,11 @@ exports.createPages = ({ graphql, boundActionCreators }) => { ` ).then(result => { if (result.errors) { - reject(new Error(result.errors)); + reject(new Error(result.errors)) } // Create image post pages. - const postTemplate = path.resolve(`src/templates/post-page.js`); + const postTemplate = path.resolve(`src/templates/post-page.js`) // We want to create a detailed page for each // Instagram post. Since the scrapped Instagram data // already includes an ID field, we just use that for @@ -211,14 +211,14 @@ exports.createPages = ({ graphql, boundActionCreators }) => { context: { id: edge.node.id, }, - }); - }); + }) + }) - return; + return }) - ); - }); -}; + ) + }) +} ``` ## Using templates @@ -237,8 +237,8 @@ we pass the id to the post. Below we use that id to query our `GraphQL` schema and return a fully formed page: ```jsx -import React from "react"; -import PostDetail from "../components/post-detail"; +import React from "react" +import PostDetail from "../components/post-detail" class PostTemplate extends React.Component { render() { @@ -246,11 +246,11 @@ class PostTemplate extends React.Component { // PostDetail is used for this detail page and // also in the modal. - ); + ) } } -export default PostTemplate; +export default PostTemplate // The post template's GraphQL query. Notice the “id” // variable which is passed in. We set this on the page @@ -282,7 +282,7 @@ export const pageQuery = ` # thumbnails are created. This makes iterating on # designs effortless as we simply change the args # for the query and we get new thumbnails. - big: sizes(maxWidth: 640) { + big: fluid(maxWidth: 640) { src srcSet } @@ -291,7 +291,7 @@ export const pageQuery = ` } } } -`; +` ``` ## Creating React.js component pages @@ -328,8 +328,8 @@ loading your site from a service worker. A small layout component might look something like this. ```jsx -import React from "react"; -import Link from "gatsby-link"; +import React from "react" +import { Link } from "gatsby" class Layout extends React.Component { render() { @@ -340,11 +340,11 @@ class Layout extends React.Component { {/* Render children pages */} {this.props.children()} - ); + ) } } -export default Layout; +export default Layout ``` Every page will be rendered as children of the `Layout` component: @@ -374,7 +374,7 @@ generates all the configuration for you. Normally page resources are pre-cached with a service worker. But as several browsers (Safari/Microsoft Edge) still don't support Service Workers, the -[Gatsby `` component](/packages/gatsby-link/) pre-caches resources for +[Gatsby `` component](/packages/gatsby/) pre-caches resources for pages it links to by loading them into memory. ## Plugins @@ -459,7 +459,7 @@ module.exports = { }, }, ], -}; +} ``` ## Styles diff --git a/docs/docs/add-custom-webpack-config.md b/docs/docs/add-custom-webpack-config.md index f6a69d2fc5f61..02d9886149b20 100644 --- a/docs/docs/add-custom-webpack-config.md +++ b/docs/docs/add-custom-webpack-config.md @@ -1,20 +1,20 @@ --- -title: "Add Custom webpack Config" +title: "Add custom webpack config" --- _Before creating custom webpack configuration, check to see if there's a Gatsby plugin already built that handles your use case in the [plugins section](/docs/plugins/). If there's not yet one and your use case is a general one, we highly encourage you to contribute back your plugin to the -Gatsby repo so it's available to others (including your future self 😀)._ +Gatsby Plugin Library so it's available to others (including your future self 😀)._ To add custom webpack configurations, create (if there's not one already) a `gatsby-node.js` file in your root directory. Inside this file, export a -function called `modifyWebpackConfig`. +function called `onCreateWebpackConfig`. When Gatsby creates its webpack config, this function will be called allowing you to modify the default webpack config using -[webpack-configurator](https://github.com/lewie9021/webpack-configurator). +[webpack-merge](https://github.com/survivejs/webpack-merge). Gatsby does multiple webpack builds with somewhat different configuration. We call each build type a "stage". The following stages exist: @@ -23,10 +23,9 @@ call each build type a "stage". The following stages exist: reloading and CSS injection into page 2. develop-html: same as develop but without react-hmre in the babel config for rendering the HTML component. -3. build-css: production build of CSS +3. build-javascript: production JavaScript and CSS build. Creates route JS bundles as well + as commons chunks for JS and CSS. 4. build-html: production build static HTML pages -5. build-javascript: production JavaScript build. Creates route bundles as well - as a `commons` and `app bundle`. Check [webpack.config.js](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/webpack.config.js) @@ -37,71 +36,62 @@ e.g. [Sass](/packages/gatsby-plugin-sass/), [Typescript](/packages/gatsby-plugin-typescript/), [Glamor](/packages/gatsby-plugin-glamor/), and many more! -## Modifying the babel loader +## Examples -Manually allow tweaking of include + exclude of babel loader. - -```javascript -const generateBabelConfig = require("gatsby/dist/utils/babel-config"); - -exports.modifyWebpackConfig = ({ config, stage }) => { - const program = { - directory: __dirname, - browserslist: ["> 1%", "last 2 versions", "IE >= 9"], - }; - - return generateBabelConfig(program, stage).then(babelConfig => { - config.removeLoader("js").loader("js", { - test: /\.jsx?$/, - exclude: modulePath => { - return ( - /node_modules/.test(modulePath) && - !/node_modules\/(swiper|dom7)/.test(modulePath) - ); - }, - loader: "babel", - query: babelConfig, - }); - }); -}; -``` - -## Example +### Flexboxgrid Here is an example that configures **flexboxgrid** when processing css files. Add this in `gatsby-node.js`: ```js -exports.modifyWebpackConfig = ({ config, stage }) => { - switch (stage) { - case "develop": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - - case "build-css": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; - - case "build-html": - config.loader("css", { - include: /flexboxgrid/, - }); - - break; +exports.onCreateWebpackConfig = ({ + stage, + rules, + loaders, + plugins, + actions, +}) => { + actions.setWebpackConfig({ + module: { + rules: [ + { + test: /\.less$/, + // We don't need to add the matching ExtractText plugin + // because gatsby already includes it and makes sure its only + // run at the appropriate stages, e.g. not in development + use: plugins.extractText.extract({ + fallback: loaders.style(), + use: [ + loaders.css({ importLoaders: 1 }), + // the postcss loader comes with some nice defaults + // including autoprefixer for our configured browsers + loaders.postcss(), + `less-loader`, + ], + }), + }, + ], + }, + plugins: [ + plugins.define({ + __DEVELOPMENT__: stage === `develop` || stage === `develop-html`, + }), + ], + }) +} +``` - case "build-javascript": - config.loader("css", { - include: /flexboxgrid/, - }); +### Absolute imports - break; - } +Instead of writing `import Header from '../../components/Header'` over and over again you can just write `import Header from 'components/Header'` with absolute imports: - return config; -}; +```js +exports.onCreateWebpackConfig = ({ stage, actions }) => { + actions.setWebpackConfig({ + resolve: { + modules: [path.resolve(__dirname, "src"), "node_modules"], + }, + }) +} ``` + +You can always find more information on _resolve_ and other options in the offical [Webpack docs](https://webpack.js.org/concepts/). diff --git a/docs/docs/adding-a-list-of-markdown-blog-posts.md b/docs/docs/adding-a-list-of-markdown-blog-posts.md index d2405fdd8b0c0..bafb6509c4420 100644 --- a/docs/docs/adding-a-list-of-markdown-blog-posts.md +++ b/docs/docs/adding-a-list-of-markdown-blog-posts.md @@ -23,8 +23,8 @@ Has anyone heard about GatsbyJS yet? The first step will be to create the page which will display your posts, in `src/pages/`. You can for example use `index.js`. ```jsx -import React from "react"; -import PostLink from "../components/post-link"; +import React from "react" +import PostLink from "../components/post-link" const IndexPage = ({ data: { @@ -33,12 +33,12 @@ const IndexPage = ({ }) => { const Posts = edges .filter(edge => !!edge.node.frontmatter.date) // You can filter your posts based on some criteria - .map(edge => ); + .map(edge => ) - return
{Posts}
; -}; + return
{Posts}
+} -export default IndexPage; +export default IndexPage ``` ### Creating the GraphQL query @@ -46,8 +46,8 @@ export default IndexPage; Second, you need to provide the data to your component with a GraphQL query. Let's add it, so that `index.js` looks like this: ```jsx -import React from "react"; -import PostLink from "../components/post-link"; +import React from "react" +import PostLink from "../components/post-link" const IndexPage = ({ data: { @@ -56,12 +56,12 @@ const IndexPage = ({ }) => { const Posts = edges .filter(edge => !!edge.node.frontmatter.date) // You can filter your posts based on some criteria - .map(edge => ); + .map(edge => ) - return
{Posts}
; -}; + return
{Posts}
+} -export default IndexPage; +export default IndexPage export const pageQuery = graphql` query IndexQuery { @@ -79,7 +79,7 @@ export const pageQuery = graphql` } } } -`; +` ``` ### Creating the `PostLink` component @@ -87,8 +87,8 @@ export const pageQuery = graphql` The only thing left to do is to add the `PostLink` component. Create a new file `post-link.js` in `src/components/` and add the following: ```jsx -import React from "react"; -import Link from "gatsby-link"; +import React from "react" +import Link from "gatsby-link" const PostLink = ({ post }) => (
@@ -96,9 +96,9 @@ const PostLink = ({ post }) => ( {post.frontmatter.title} ({post.frontmatter.date})
-); +) -export default PostLink; +export default PostLink ``` This should get you a page with your posts sorted by descending date. You can further customise the `frontmatter` and the page and `PostLink` components to get your desired effects! diff --git a/docs/docs/adding-images-fonts-files.md b/docs/docs/adding-images-fonts-files.md index 688ad8fb85b20..ef2d93082b68e 100644 --- a/docs/docs/adding-images-fonts-files.md +++ b/docs/docs/adding-images-fonts-files.md @@ -17,17 +17,17 @@ jpeg, png, gif, mp4, webm, wav, mp3, m4a, aac, and oga. Here is an example: ```js -import React from "react"; -import logo from "./logo.png"; // Tell Webpack this JS file uses this image +import React from "react" +import logo from "./logo.png" // Tell Webpack this JS file uses this image -console.log(logo); // /logo.84287d09.png +console.log(logo) // /logo.84287d09.png function Header() { // Import result is the URL of your image - return Logo; + return Logo } -export default Header; +export default Header ``` This ensures that when the project is built, Webpack will correctly move the @@ -126,12 +126,12 @@ If you put a file into the `static` folder, it will **not** be processed by Webpack. Instead it will be copied into the public folder untouched. E.g. if you add a file named `sun.jpg` to the static folder, it'll be copied to `public/sun.jpg`. To reference assets in the `static` folder, you'll need to -[import a helper function from `gatsby-link` named `withPrefix`](/packages/gatsby-link/#prefixed-paths-helper). +[import a helper function from `gatsby` named `withPrefix`](/packages/gatsby/#prefixed-paths-helper). You will need to make sure [you set `pathPrefix` in your gatsby-config.js for this to work](/docs/path-prefix/). ```js -import { withPrefix } from 'gatsby-link' +import { withPrefix } from 'gatsby' render() { // Note: this is an escape hatch and should be used sparingly! diff --git a/docs/docs/adding-markdown-pages.md b/docs/docs/adding-markdown-pages.md index 964523038e493..56539fe2c5563 100644 --- a/docs/docs/adding-markdown-pages.md +++ b/docs/docs/adding-markdown-pages.md @@ -34,7 +34,7 @@ plugins: [ name: "markdown-pages", }, }, -]; +] ``` Now that we've "sourced" the markdown files from the filesystem, we can now "transform" the markdown to HTML and the YAML frontmatter to JSON. @@ -57,7 +57,7 @@ plugins: [ }, }, `gatsby-transformer-remark`, -]; +] ``` #### Note on creating markdown files. @@ -78,13 +78,13 @@ Create a folder in the `/src` directory of your Gatsby application called `templ Now create a `blogTemplate.js` inside it with the following content. ```jsx -import React from "react"; +import React from "react" export default function Template({ data, // this prop will be injected by the GraphQL query below. }) { - const { markdownRemark } = data; // data.markdownRemark holds our post data - const { frontmatter, html } = markdownRemark; + const { markdownRemark } = data // data.markdownRemark holds our post data + const { frontmatter, html } = markdownRemark return (
@@ -96,7 +96,7 @@ export default function Template({ />
- ); + ) } export const pageQuery = graphql` @@ -110,7 +110,7 @@ export const pageQuery = graphql` } } } -`; +` ``` Two things are important in the file above. @@ -126,12 +126,12 @@ Gatsby exposes a powerful Node.js API, which allows for functionality such as cr Gatsby calls the `createPages` API (if present) at build time with injected parameters, `boundActionCreators` and `graphql`. Use the `graphql` to query Markdown file data as below. Next use `createPage` action creator to create a page for each of the Markdown files using the `blogTemplate.js` we created in the previous step. ```javascript -const path = require("path"); +const path = require("path") exports.createPages = ({ boundActionCreators, graphql }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators - const blogPostTemplate = path.resolve(`src/templates/blogTemplate.js`); + const blogPostTemplate = path.resolve(`src/templates/blogTemplate.js`) return graphql(` { @@ -150,7 +150,7 @@ exports.createPages = ({ boundActionCreators, graphql }) => { } `).then(result => { if (result.errors) { - return Promise.reject(result.errors); + return Promise.reject(result.errors) } result.data.allMarkdownRemark.edges.forEach(({ node }) => { @@ -158,10 +158,10 @@ exports.createPages = ({ boundActionCreators, graphql }) => { path: node.frontmatter.path, component: blogPostTemplate, context: {}, // additional data can be passed via context - }); - }); - }); -}; + }) + }) + }) +} ``` This should get you started on some basic markdown power in your Gatsby site. You can further customise the `frontmatter` and the template file to get desired effects! diff --git a/docs/docs/adding-search.md b/docs/docs/adding-search.md index 2df473339fc9e..4cc0a3e886ca2 100644 --- a/docs/docs/adding-search.md +++ b/docs/docs/adding-search.md @@ -2,6 +2,8 @@ title: "Adding search to your Gatsby website" --- +Before we go through the steps for adding search to your Gatsby website, let's examine the components needed for adding search to a website. + There are three required components for adding search to your Gatsby website: 1. index diff --git a/docs/docs/adding-tags-and-categories-to-blog-posts.md b/docs/docs/adding-tags-and-categories-to-blog-posts.md index 5136ef3aa3cc3..13f8c351ff88f 100644 --- a/docs/docs/adding-tags-and-categories-to-blog-posts.md +++ b/docs/docs/adding-tags-and-categories-to-blog-posts.md @@ -73,30 +73,30 @@ If you followed the tutorial for [Adding Markdown Pages](/docs/adding-markdown-p First, we'll add a tags template at `src/templates/tags.js`: ```jsx -import React from "react"; -import PropTypes from "prop-types"; +import React from "react" +import PropTypes from "prop-types" // Components -import Link from "gatsby-link"; +import Link from "gatsby-link" const Tags = ({ pathContext, data }) => { - const { tag } = pathContext; - const { edges, totalCount } = data.allMarkdownRemark; + const { tag } = pathContext + const { edges, totalCount } = data.allMarkdownRemark const tagHeader = `${totalCount} post${ totalCount === 1 ? "" : "s" - } tagged with "${tag}"`; + } tagged with "${tag}"` return (

{tagHeader}

    {edges.map(({ node }) => { - const { path, title } = node.frontmatter; + const { path, title } = node.frontmatter return (
  • {title}
  • - ); + ) })}
{/* @@ -105,8 +105,8 @@ const Tags = ({ pathContext, data }) => { */} All tags
- ); -}; + ) +} Tags.propTypes = { pathContext: PropTypes.shape({ @@ -127,9 +127,9 @@ Tags.propTypes = { ), }), }), -}; +} -export default Tags; +export default Tags export const pageQuery = graphql` query TagPage($tag: String) { @@ -149,7 +149,7 @@ export const pageQuery = graphql` } } } -`; +` ``` **Note**: `propTypes` are included in this example to help you ensure you're getting all the data you need in the component, and to help serve as a guide while destructuring / using those props. @@ -159,13 +159,13 @@ export const pageQuery = graphql` Now we've got a template. Great! I'll assume you followed the tutorial for [Adding Markdown Pages](/docs/adding-markdown-pages/) and provide a sample `createPages` that generates post pages as well as tag pages. In the site's `gatsby-node.js` file, include `lodash` (`const _ = require('lodash')`) and then make sure your [`createPages`](/docs/node-apis/#createPages) looks something like this: ```js -const path = require("path"); +const path = require("path") exports.createPages = ({ boundActionCreators, graphql }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators - const blogPostTemplate = path.resolve("src/templates/blog.js"); - const tagTemplate = path.resolve("src/templates/tags.js"); + const blogPostTemplate = path.resolve("src/templates/blog.js") + const tagTemplate = path.resolve("src/templates/tags.js") return graphql(` { @@ -185,29 +185,29 @@ exports.createPages = ({ boundActionCreators, graphql }) => { } `).then(result => { if (result.errors) { - return Promise.reject(result.errors); + return Promise.reject(result.errors) } - const posts = result.data.allMarkdownRemark.edges; + const posts = result.data.allMarkdownRemark.edges // Create post detail pages posts.forEach(({ node }) => { createPage({ path: node.frontmatter.path, component: blogPostTemplate, - }); - }); + }) + }) // Tag pages: - let tags = []; + let tags = [] // Iterate through each post, putting all found tags into `tags` _.each(posts, edge => { if (_.get(edge, "node.frontmatter.tags")) { - tags = tags.concat(edge.node.frontmatter.tags); + tags = tags.concat(edge.node.frontmatter.tags) } - }); + }) // Eliminate duplicate tags - tags = _.uniq(tags); + tags = _.uniq(tags) // Make tag pages tags.forEach(tag => { @@ -217,10 +217,10 @@ exports.createPages = ({ boundActionCreators, graphql }) => { context: { tag, }, - }); - }); - }); -}; + }) + }) + }) +} ``` Some notes: @@ -233,15 +233,15 @@ Some notes: Our `/tags` page will simply list out all tags, followed by the number of posts with that tag: ```jsx -import React from "react"; -import PropTypes from "prop-types"; +import React from "react" +import PropTypes from "prop-types" // Utilities -import kebabCase from "lodash/kebabCase"; +import kebabCase from "lodash/kebabCase" // Components -import Helmet from "react-helmet"; -import Link from "gatsby-link"; +import Helmet from "react-helmet" +import Link from "gatsby-link" const TagsPage = ({ data: { @@ -266,7 +266,7 @@ const TagsPage = ({ -); +) TagsPage.propTypes = { data: PropTypes.shape({ @@ -284,9 +284,9 @@ TagsPage.propTypes = { }), }), }), -}; +} -export default TagsPage; +export default TagsPage export const pageQuery = graphql` query TagsQuery { @@ -305,7 +305,7 @@ export const pageQuery = graphql` } } } -`; +` ``` ## _(optional)_ Render tags inline with your blog posts diff --git a/docs/docs/api-proxy.md b/docs/docs/api-proxy.md index d3376bce848bc..195754561e21b 100644 --- a/docs/docs/api-proxy.md +++ b/docs/docs/api-proxy.md @@ -14,7 +14,7 @@ module.exports = { prefix: "/api", url: "http://dev-mysite.com", }, -}; +} ``` This way, when you `fetch('/api/todos')` in development, the development server @@ -31,7 +31,7 @@ Gatsby exposes the [Express.js](https://expressjs.com/) develop server to your s can add Express middleware as needed. ```javascript -var proxy = require("http-proxy-middleware"); +var proxy = require("http-proxy-middleware") module.exports = { developMiddleware: app => { @@ -43,9 +43,9 @@ module.exports = { "/.netlify/functions/": "", }, }) - ); + ) }, -}; +} ``` Keep in mind that middleware only has effect in development (with gatsby develop). diff --git a/docs/docs/api-specification.md b/docs/docs/api-specification.md index bdd0f47bca18e..d1d6b0cfeaf5b 100644 --- a/docs/docs/api-specification.md +++ b/docs/docs/api-specification.md @@ -56,9 +56,9 @@ See ## Concepts - _Page_ — a site page with a pathname, a template component, and optional - graphql query and layout component + graphql query. - _Page Component_ — React.js component that renders a page and can optionally - specify a layout component and a graphql query + specify a graphql query - _Component extensions_ — extensions that are resolvable as components. `.js` and `.jsx` are supported by core. But plugins can add support for other compile-to-js languages. diff --git a/docs/docs/babel.md b/docs/docs/babel.md new file mode 100644 index 0000000000000..c5a8cc482f418 --- /dev/null +++ b/docs/docs/babel.md @@ -0,0 +1,72 @@ +--- +title: Babel +--- + +Gatsby uses the phenomenal project [Babel](https://babeljs.io/) to enable +support for writing modern JavaScript — while still supporting older browsers. + +## How to specify which browsers to support + +Gatsby supports by default the last two versions of major browsers, IE 9+, as well as +any browser that still as 1%+ browser share. + +This means we automatically compile your JavaScript to ensure it works on older browsers. +We also automatically add polyfills as needed — no more shipping code which mysteriously +breaks on older browsers! + +If you only target newer browsers, see the [Browser +Support](/docs/browser-support/) docs page for how to instruct Gatsby on which +browsers you support and then Babel will start compiling for only these +browsers. + +## How to use a custom .babelrc file + +Gatsby ships with a default .babelrc setup that should work for most sites. If you'd like +to add custom Babel presets or plugins, we recommend copying our default .bablerc below +to root of your site and modifying it per your needs. + +```json5 +{ + cacheDirectory: true, + babelrc: false, + presets: [ + [ + "@babel/preset-env", + { + loose: true, + modules: false, + useBuiltIns: "usage", + shippedProposals: true, + targets: { + browsers: [">0.25%", "not dead"], + }, + }, + ], + [ + "@babel/preset-react", + { + useBuiltIns: true, + pragma: "React.createElement", + }, + ], + "@babel/preset-flow", + ], + plugins: [ + [ + "@babel/plugin-proposal/class-properties", + { + loose: true, + }, + ], + "@babel/plugin-syntax-dynamic-import", + [ + "@babel/plugin-transform-runtime", + { + helpers: true, + regenerator: true, + polyfill: false, + }, + ], + ], +} +``` diff --git a/docs/docs/browser-support.md b/docs/docs/browser-support.md index 24ddad5864ee1..781d13634233c 100644 --- a/docs/docs/browser-support.md +++ b/docs/docs/browser-support.md @@ -9,17 +9,17 @@ browsers. ## Polyfills -Gatsby uses the ES6 Promise API. As some older browsers don't support this, -Gatsby includes by default a Promise polyfill. If you would like to provide your -own Promise polyfill, you can set `polyfill` to `false` in your -`gatsby-config.js`: +Gatsby leverages Babel 7's ability to automatically add polyfills for your +target browsers. -``` -module.exports = { - polyfill: false, - // ... -} -``` +Newer browsers support more JavaScript APIs than older browsers. For older +versions, Gatsby (via Babel) automatically adds the minimum "polyfills" +necessary for your code to work in those browsers. + +If you start using a newer JavaScript API like `[].includes` that isn't +supported by some of your targeted browsers, you won't have to worry about it +breaking the older browsers as Babel will automatically add the needed polyfill +`core-js/modules/es7.array.includes`. ## Specify what browsers your project supports using "Browserslist" @@ -39,9 +39,11 @@ By default, Gatsby emulates the following config: // package.json { "browserslist": [ - "> 1%", - "IE >= 9", - "last 2 versions" + ">0.25%", + "not dead" ] } ``` + +If you only support newer browsers then make sure to specify this in your +package.json as you'll often be able then to ship smaller JavaScript files. diff --git a/docs/docs/building-apps-with-gatsby.md b/docs/docs/building-apps-with-gatsby.md index f7ef4e70b9fca..a18cc40abc4c2 100644 --- a/docs/docs/building-apps-with-gatsby.md +++ b/docs/docs/building-apps-with-gatsby.md @@ -36,17 +36,17 @@ _Note: There's also a plugin that can aid in creating client-only routes: // Implement the Gatsby API “onCreatePage”. This is // called after every page is created. exports.onCreatePage = async ({ page, boundActionCreators }) => { - const { createPage } = boundActionCreators; + const { createPage } = boundActionCreators // page.matchPath is a special key that's used for matching pages // only on the client. if (page.path.match(/^\/app/)) { - page.matchPath = "/app/:path"; + page.matchPath = "/app/:path" // Update the page. - createPage(page); + createPage(page) } -}; +} ``` The [example site "simple auth"](https://github.com/gatsbyjs/gatsby/blob/master/examples/simple-auth/README.md) demos how to combine user authentication with restricted client-only routes. diff --git a/docs/docs/building-with-components.md b/docs/docs/building-with-components.md index a0f848b3a2398..523ec558b9c55 100644 --- a/docs/docs/building-with-components.md +++ b/docs/docs/building-with-components.md @@ -40,10 +40,7 @@ A basic directory structure of a project might look like this:    │      └── 01-03-2017    │         └── index.md    ├── templates -    │ └── post.jsx - │ - └── layouts - └── index.jsx +    └── post.jsx ``` ### Page components @@ -59,7 +56,7 @@ Example: `src/pages/about.jsx` ```jsx -import React, { Component } from "react"; +import React, { Component } from "react" class AboutPage extends Component { render() { @@ -67,11 +64,11 @@ class AboutPage extends Component {

About me.

- ); + ) } } -export default AboutPage; +export default AboutPage ``` ### Page template components @@ -88,22 +85,22 @@ introduction to programmatically creating pages. Example: ```jsx -import React from "react"; +import React from "react" class BlogPostTemplate extends React.Component { render() { - const post = this.props.data.markdownRemark; + const post = this.props.data.markdownRemark return (

{post.frontmatter.title}

- ); + ) } } -export default BlogPostTemplate; +export default BlogPostTemplate export const pageQuery = graphql` query BlogPostBySlug($slug: String!) { @@ -114,32 +111,7 @@ export const pageQuery = graphql` } } } -`; -``` - -### Layout components - -`src/layouts/index.jsx` (optional) wraps page components. You can use it for -portions of pages that are shared across pages like headers and footers. - -You can use the `location` prop to render conditionally based on the page -URL. - -Example: - -```jsx -import React from "react"; -import Navigation from "../components/Navigation/Navigation.jsx"; - -export default class Template extends React.Component { - render() { - if (this.props.location.pathname !== "/") { - return {this.props.children()}; - } else { - return this.props.children(); - } - } -} +` ``` ### HTML component @@ -157,28 +129,28 @@ have an html.js. Example: ```jsx -import React from "react"; -import favicon from "./favicon.png"; +import React from "react" +import favicon from "./favicon.png" -let inlinedStyles = ""; +let inlinedStyles = "" if (process.env.NODE_ENV === "production") { try { - inlinedStyles = require("!raw-loader!../public/styles.css"); + inlinedStyles = require("!raw-loader!../public/styles.css") } catch (e) { - console.log(e); + console.log(e) } } export default class HTML extends React.Component { render() { - let css; + let css if (process.env.NODE_ENV === "production") { css = (