Skip to content

Commit

Permalink
Merge branch 'canary' into font-webpack5
Browse files Browse the repository at this point in the history
  • Loading branch information
prateekbh committed Oct 5, 2020
2 parents 3746058 + 06a8b1a commit b11d239
Show file tree
Hide file tree
Showing 20 changed files with 442 additions and 55 deletions.
9 changes: 9 additions & 0 deletions .github/actions/next-stats-action/src/index.js
@@ -1,3 +1,5 @@
const path = require('path')
const fs = require('fs-extra')
const exec = require('./util/exec')
const logger = require('./util/logger')
const runConfigs = require('./run')
Expand Down Expand Up @@ -25,6 +27,13 @@ if (!allowedActions.has(actionInfo.actionName) && !actionInfo.isRelease) {

;(async () => {
try {
if (await fs.pathExists(path.join(__dirname, '../SKIP_NEXT_STATS.txt'))) {
console.log(
'SKIP_NEXT_STATS.txt file present, exiting stats generation..'
)
process.exit(0)
}

const { stdout: gitName } = await exec(
'git config user.name && git config user.email'
)
Expand Down
4 changes: 3 additions & 1 deletion .github/actions/next-stats-action/src/prepare/action-info.js
Expand Up @@ -56,7 +56,9 @@ module.exports = function actionInfo() {
isLocal: LOCAL_STATS,
commitId: null,
issueId: ISSUE_ID,
isRelease: releaseTypes.has(GITHUB_ACTION),
isRelease:
GITHUB_REPOSITORY === 'vercel/next.js' &&
(GITHUB_REF || '').includes('canary'),
}

// get comment
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/build_test_deploy.yml
Expand Up @@ -185,3 +185,14 @@ jobs:
key: ${{ github.sha }}

- run: ./publish-release.sh

prStats:
name: Release Stats
runs-on: ubuntu-latest
needs: [publishRelease]
steps:
- uses: actions/checkout@v2
- run: ./release-stats.sh
- uses: ./.github/actions/next-stats-action
env:
PR_STATS_COMMENT_TOKEN: ${{ secrets.PR_STATS_COMMENT_TOKEN }}
13 changes: 0 additions & 13 deletions .github/workflows/release_stats.yml

This file was deleted.

2 changes: 2 additions & 0 deletions docs/api-reference/next.config.js/exportPathMap.md
Expand Up @@ -13,6 +13,8 @@ description: Customize the pages that will be exported as HTML files when using
</ul>
</details>

`exportPathMap` allows you to specify a mapping of request paths to page destinations, to be used during export.

Let's start with an example, to create a custom `exportPathMap` for an app with the following pages:

- `pages/index.js`
Expand Down
9 changes: 9 additions & 0 deletions docs/manifest.json
Expand Up @@ -187,6 +187,15 @@
"title": "Upgrade Guide",
"path": "/docs/upgrading.md"
},
{
"title": "Migrating to Next.js",
"routes": [
{
"title": "Migrating from Gatsby",
"path": "/docs/migrating/from-gatsby.md"
}
]
},
{ "title": "FAQ", "path": "/docs/faq.md" }
]
},
Expand Down
253 changes: 253 additions & 0 deletions docs/migrating/from-gatsby.md
@@ -0,0 +1,253 @@
---
description: Learn how to transition an existing Gatsby project to Next.js.
---

# Migrating from Gatsby

This guide will help you understand how to transition from an existing Gatsby project to Next.js. Migrating to Next.js will allow you to:

- Choose which [data fetching](/docs/basic-features/data-fetching.md) strategy you want on a per-page basis.
- Use [Incremental Static Regeneration](/docs/basic-features/data-fetching.md#incremental-static-regeneration) to update _existing_ pages by re-rendering them in the background as traffic comes in.
- Use [API Routes](/docs/api-routes/introduction.md).

And more! Let’s walk through a series of steps to complete the migration.

## Updating `package.json` and dependencies

The first step towards migrating to Next.js is to update `package.json` and dependencies. You should:

- Remove all Gatsby-related packages (but keep `react` and `react-dom`).
- Install `next`.
- Add Next.js related commands to `scripts`. One is `next dev`, which runs a development server at `localhost:3000`. You should also add `next build` and `next start` for creating and starting a production build.

Here's an example `package.json` ([view diff](https://github.com/leerob/gatsby-to-nextjs/pull/1/files#diff-b9cfc7f2cdf78a7f4b91a753d10865a2)):

```json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "latest",
"react-dom": "latest"
}
}
```

## Static Assets and Compiled Output

Gatsby uses the `public` directory for the compiled output, whereas Next.js uses it for static assets. Here are the steps for migration ([view diff](https://github.com/leerob/gatsby-to-nextjs/pull/1/files#diff-a084b794bc0759e7a6b77810e01874f2)):

- Remove `.cache/` and `public` from `.gitignore` and delete both directories.
- Rename Gatsby’s `static` directory as `public`.
- Add `.next` to `.gitignore`.

## Creating Routes

Both Gatsby and Next support a `pages` directory, which uses [file-system based routing](/docs/routing/introduction.md). Gatsby's directory is `src/pages`, which is also [supported by Next.js](/docs/advanced-features/src-directory.md).

Gatsby creates dynamic routes using the `createPages` API inside of `gatsby-node.js`. With Next, we can use [Dynamic Routes](/docs/routing/dynamic-routes.md) inside of `pages` to achieve the same effect. Rather than having a `template` directory, you can use the React component inside your dynamic route file. For example:

- **Gatsby:** `createPages` API inside `gatsby-node.js` for each blog post, then have a template file at `src/templates/blog-post.js`.
- **Next:** Create `pages/blog/[slug].js` which contains the blog post template. The value of `slug` is accessible through a [query parameter](/docs/routing/dynamic-routes.md). For example, the route `/blog/first-post` would forward the query object `{ 'slug': 'first-post' }` to `pages/blog/[slug].js` ([learn more here](/docs/basic-features/data-fetching.md#getstaticpaths-static-generation`)).

## Styling

With Gatsby, global CSS imports are included in `gatsby-browser.js`. With Next, you should create a [custom `_app.js`](/docs/advanced-features/custom-app.md) for global CSS. When migrating, you can copy over your CSS imports directly and update the relative file path, if necessary. Next.js has [built-in CSS support](/docs/basic-features/built-in-css-support.md).

## Links

The Gatsby `Link` and Next.js [`Link`](/docs/api-reference/next/link.md) component have a slightly different API. First, you will need to update any import statements referencing `Link` from Gatsby to:

```js
import Link from 'next/link'
```

Next, you can find and replace usages of `to="/route"` with `href="/route"`.

## Data Fetching

The largest difference between Gatsby and Next.js is how data fetching is implemented. Gatsby is opinionated with GraphQL being the default strategy for retrieving data across your application. With Next.js, you get to choose which strategy you want (GraphQL is one supported option).

Gatsby uses the `graphql` tag to query data in the pages of your site. This may include local data, remote data, or information about your site configuration. Gatsby only allows the creation of static pages. With Next.js, you can choose on a [per-page basis](/docs/basic-features/pages.md) which [data fetching strategy](/docs/basic-features/data-fetching.md) you want. For example, `getServerSideProps` allows you to do server-side rendering. If you wanted to generate a static page, you'd export `getStaticProps` / `getStaticPaths` inside the page, rather than using `pageQuery`. For example:

```js
// src/pages/[slug].js

// Install remark and remark-html
import remark from 'remark'
import html from 'remark-html'
import { getPostBySlug, getAllPosts } from '../lib/blog'

export async function getStaticProps({ params }) {
const post = getPostBySlug(params.slug)
const content = await remark()
.use(html)
.process(post.content || '')
.toString()

return {
props: {
...post,
content,
},
}
}

export async function getStaticPaths() {
const posts = getAllPosts()

return {
paths: posts.map((post) => {
return {
params: {
slug: post.slug,
},
}
}),
fallback: false,
}
}
```

You'll commonly see Gatsby plugins used for reading the file system (`gatsby-source-filesystem`), handling markdown files (`gatsby-transformer-remark`), and so on. For example, the popular starter blog example has [15 Gatsby specific packages](https://github.com/gatsbyjs/gatsby-starter-blog/blob/master/package.json). Next takes a different approach. It includes common features like [image optimization](https://github.com/vercel/next.js/discussions/17141) directly inside the framework, and gives the user full control over integrations with external packages. For example, rather than abstracting reading from the file system to a plugin, you can use the native Node.js `fs` package inside `getStaticProps` / `getStaticPaths` to read from the file system.

```js
// src/lib/blog.js

// Install gray-matter and date-fns
import matter from 'gray-matter'
import { parseISO, format } from 'date-fns'
import fs from 'fs'
import { join } from 'path'

// Add markdown files in `src/content/blog`
const postsDirectory = join(process.cwd(), 'src', 'content', 'blog')

export function getPostBySlug(slug) {
const realSlug = slug.replace(/\\.md$/, '')
const fullPath = join(postsDirectory, `${realSlug}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const { data, content } = matter(fileContents)
const date = format(parseISO(data.date), 'MMMM dd, yyyy')

return { slug: realSlug, frontmatter: { ...data, date }, content }
}

export function getAllPosts() {
const slugs = fs.readdirSync(postsDirectory)
const posts = slugs.map((slug) => getPostBySlug(slug))

return posts
}
```

## Site Configuration

With Gatsby, your site's metadata (name, description, etc) is located inside `gatsby-config.js`. This is then exposed through the GraphQL API and consumed through a `pageQuery` or a static query inside a component.

With Next.js, we recommend creating a config file similar to below. You can then import this file anywhere without having to use GraphQL to access your site's metadata.

```js
// src/config.js

export default {
title: 'Starter Blog',
author: {
name: 'Lee Robinson',
summary: 'who loves Next.js.',
},
description: 'A starter blog converting Gatsby -> Next.',
social: {
twitter: 'leeerob',
},
}
```

## Search Engine Optimization

Most Gatsby examples use `react-helmet` to assist with adding `meta` tags for proper SEO. With Next.js, we recommend using [`next/head`](/docs/api-reference/next/head.md) to add `meta` tags to your `<head />` element. For example, here's part of an SEO component with Gatsby:

```js
// src/components/seo.js

import { Helmet } from 'react-helmet'

export default function SEO({ description, title, siteTitle }) {
return (
<Helmet
title={title}
titleTemplate={siteTitle ? `%s | ${siteTitle}` : null}
meta={[
{
name: `description`,
content: description,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: description,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: twitter,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: description,
},
]}
/>
)
}
```

And here's the same example using Next.js, including reading from a site config file.

```js
// src/components/seo.js

import Head from 'next/head'
import config from '../config'

export default function SEO({ description, title }) {
const siteTitle = config.title

return (
<Head>
<title>{`${title} | ${siteTitle}`}</title>
<meta name="description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:site_name" content={siteTitle} />
<meta property="twitter:card" content="summary" />
<meta property="twitter:creator" content={config.social.twitter} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
</Head>
)
}
```

## Learn more

Please take a look at [this pull request](https://github.com/leerob/gatsby-to-nextjs/pull/1) to learn more. If you have questions, please ask on [our discussion board](https://github.com/vercel/next.js/discussions).
19 changes: 19 additions & 0 deletions errors/export-no-custom-routes.md
@@ -0,0 +1,19 @@
# `next export` No Custom Routes

#### Why This Error Occurred

In your `next.config.js` `rewrites`, `redirects`, or `headers` were defined while `next export` was being run outside of a platform that supports them.

These configs do not apply when exporting your Next.js application manually.

#### Possible Ways to Fix It

Disable the `rewrites`, `redirects`, and `headers` from your `next.config.js` when using `next export` to deploy your application or deploy your application using [a method](https://nextjs.org/docs/deployment#vercel-recommended) that supports these configs.

### Useful Links

- [Deployment Documentation](https://nextjs.org/docs/deployment#vercel-recommended)
- [`next export` Documentation](https://nextjs.org/docs/advanced-features/static-html-export)
- [Rewrites Documentation](https://nextjs.org/docs/api-reference/next.config.js/rewrites)
- [Redirects Documentation](https://nextjs.org/docs/api-reference/next.config.js/redirects)
- [Headers Documentation](https://nextjs.org/docs/api-reference/next.config.js/headers)
2 changes: 1 addition & 1 deletion examples/amp-first/README.md
Expand Up @@ -60,7 +60,7 @@ Things you need to do after installing the boilerplate:
```

- **amp-list & amp-mustache:** mustache templates conflict with JSX and it's template literals need to be escaped. A simple approach is to escape them via back ticks: `` src={`{{imageUrl}}`} ``.
- **amp-script:** you can use [amp-script](https://amp.dev/documentation/components/amp-script/) to add custom JavaScript to your AMP pages. The boilerplate includes a helper [`components/amp/AmpScript.js`](components/amp/AmpScript.js) to simplify using amp-script. The helper also supports embedding inline scripts. Good to know: Next.js uses [AMP Optimizer](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer) under the hood, which automatically adds the needed script hashes for [inline amp-scripts](https://amp.dev/documentation/components/amp-script/#load-javascript-from-a-local-element).
- **amp-script:** you can use [amp-script](https://amp.dev/documentation/components/amp-script/) to add custom JavaScript to your AMP pages. The boilerplate includes a helper [`components/amp/AmpScript.js`](components/amp/AmpScript.js) to simplify using `amp-script`. The helper also supports embedding inline scripts. Good to know: Next.js uses [AMP Optimizer](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer) under the hood, which automatically adds the needed script hashes for [inline amp-scripts](https://amp.dev/documentation/components/amp-script/#load-javascript-from-a-local-element).

## Deployment

Expand Down
2 changes: 1 addition & 1 deletion examples/api-routes-rest/README.md
@@ -1,6 +1,6 @@
# API routes with REST

Next.js ships with [API routes](https://github.com/vercel/next.js#api-routes), which provide an easy solution to build your own `API`. This example shows how it can be used to create your [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) api.
Next.js ships with [API routes](https://github.com/vercel/next.js#api-routes), which provide an easy solution to build your own `API`. This example shows how it can be used to create your [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) `API`.

## Deploy your own

Expand Down
6 changes: 3 additions & 3 deletions examples/blog-starter-typescript/README.md
Expand Up @@ -2,11 +2,11 @@

This is the existing [blog-starter](https://github.com/vercel/next.js/tree/canary/examples/blog-starter) plus TypeScript.

This example showcases Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature using markdown files as the data source.
This example showcases Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature using Markdown files as the data source.

The blog posts are stored in `/_posts` as markdown files with front matter support. Adding a new markdown file in there will create a new blog post.
The blog posts are stored in `/_posts` as Markdown files with front matter support. Adding a new Markdown file in there will create a new blog post.

To create the blog posts we use [`remark`](https://github.com/remarkjs/remark) and [`remark-html`](https://github.com/remarkjs/remark-html) to convert the markdown files into an HTML string, and then send it down as a prop to the page. The metadata of every post is handled by [`gray-matter`](https://github.com/jonschlinkert/gray-matter) and also sent in props to the page.
To create the blog posts we use [`remark`](https://github.com/remarkjs/remark) and [`remark-html`](https://github.com/remarkjs/remark-html) to convert the Markdown files into an HTML string, and then send it down as a prop to the page. The metadata of every post is handled by [`gray-matter`](https://github.com/jonschlinkert/gray-matter) and also sent in props to the page.

## How to use

Expand Down

0 comments on commit b11d239

Please sign in to comment.