Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Port 'with-static-export' example to TypeScript #38268

Merged
Merged
42 changes: 42 additions & 0 deletions examples/with-static-export-typescript/.gitignore
@@ -0,0 +1,42 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
.pnpm*
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel

# typescript
*.tsbuildinfo

# cache
.swc/

25 changes: 25 additions & 0 deletions examples/with-static-export-typescript/README.md
@@ -0,0 +1,25 @@
# Static export example with TypeScript

This example shows how to use Next.js's [Static Generation](https://nextjs.org/docs/basic-features/pages) feature to export to static HTML files your Next.js application, fetching data from an API to generate a dynamic list of pages.

This is a TypeScript version of the [with-static-export](https://github.com/vercel/next.js/tree/canary/examples/with-static-export) example.

When trying to run `npm start` it will build and export your pages into the `out` folder and serve them on `localhost:5000`.

## Deploy your own

Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-static-export-typescript)

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-static-export-typescript)

## How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:

```bash
npx create-next-app --example with-static-export-typescript with-static-export-typescript-app
# or
yarn create next-app --example with-static-export-typescript with-static-export-typescript-app
# or
pnpm create next-app --example with-static-export-typescript with-static-export-typescript-app
```
14 changes: 14 additions & 0 deletions examples/with-static-export-typescript/components/post.tsx
@@ -0,0 +1,14 @@
import Link from 'next/link'
import { PostData } from '../types/postdata'

export default function Post({ id, title, body }: PostData) {
return (
<article>
<h2>{title}</h2>
<p>{body}</p>
<Link href={`/post/${id}`}>
<a>Read more...</a>
</Link>
</article>
)
}
17 changes: 17 additions & 0 deletions examples/with-static-export-typescript/lib/postdata_api.ts
@@ -0,0 +1,17 @@
import { PostData } from '../types/postdata'

export async function GetPost(id: string): Promise<PostData> {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
)
const postData: PostData = (await response.json()) as PostData
return postData
}

export async function GetPosts(): Promise<PostData[]> {
const response = await fetch(
'https://jsonplaceholder.typicode.com/posts?_page=1'
)
const postList: PostData[] = (await response.json()) as PostData[]
return postList
}
5 changes: 5 additions & 0 deletions examples/with-static-export-typescript/next-env.d.ts
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
26 changes: 26 additions & 0 deletions examples/with-static-export-typescript/package.json
@@ -0,0 +1,26 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"preexport": "npm run build",
"export": "next export",
"prestart": "npm run export",
"start": "serve out",
"lint": "next lint"
},
"dependencies": {
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"serve": "^13.0.2"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5",
"eslint": "8.19.0",
"eslint-config-next": "12.2.0",
"typescript": "^4.7.4"
}
}
35 changes: 35 additions & 0 deletions examples/with-static-export-typescript/pages/index.tsx
@@ -0,0 +1,35 @@
import Head from 'next/head'
import { GetStaticProps, NextPage } from 'next'
import Post from '../components/post'
import { PostData, PostDataListProps } from '../types/postdata'
import { GetPosts } from '../lib/postdata_api'

export const getStaticProps: GetStaticProps = async (_context) => {
// fetch list of posts
const posts: PostData[] = await GetPosts()
return {
props: {
postDataList: posts,
},
}
}

const IndexPage: NextPage<PostDataListProps> = ({ postDataList }: PostDataListProps) => {
return (
<main>
<Head>
<title>Home page</title>
</Head>

<h1>List of posts</h1>

<section>
{postDataList.map((post: PostData) => (
<Post {...post} key={post.id} />
))}
</section>
</main>
)
}

export default IndexPage
57 changes: 57 additions & 0 deletions examples/with-static-export-typescript/pages/post/[id].tsx
@@ -0,0 +1,57 @@
import Link from 'next/link'
import Head from 'next/head'
import React from 'react'
import { GetStaticProps, GetStaticPaths, NextPage } from 'next'
import { ParsedUrlQuery } from 'querystring'
import { PostData, PostDataProps } from '../../types/postdata'
import { GetPosts, GetPost } from '../../lib/postdata_api'

interface Params extends ParsedUrlQuery {
id: string
}

export const getStaticPaths: GetStaticPaths<Params> = async () => {
const postList: PostData[] = await GetPosts()
return {
paths: postList.map((post) => {
return {
params: {
id: `$(post.id)`,
},
}
}),
fallback: false,
}
}

export const getStaticProps: GetStaticProps<PostDataProps, Params> = async (
context
) => {
const { id } = context.params! as Params
const postData: PostData = await GetPost(id)
return {
props: {
postData,
},
}
}

const Post: NextPage<PostDataProps> = ({ postData } : PostDataProps) => {
return (
<main>
<Head>
<title>{postData.title}</title>
</Head>

<h1>{postData.title}</h1>

<p>{postData.body}</p>

<Link href="/">
<a>Go back to home</a>
</Link>
</main>
)
}

export default Post
20 changes: 20 additions & 0 deletions examples/with-static-export-typescript/tsconfig.json
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"moduleResolution": "node"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
14 changes: 14 additions & 0 deletions examples/with-static-export-typescript/types/postdata.ts
@@ -0,0 +1,14 @@
export interface PostData {
userId: number
id: number
title: string
body: string
}

export interface PostDataProps {
postData: PostData
}

export interface PostDataListProps {
postDataList: PostData[]
}