Skip to content

Commit 68c2dd6

Browse files
committed
fix tutorial-config.md
1 parent 5f36d72 commit 68c2dd6

File tree

1 file changed

+220
-67
lines changed

1 file changed

+220
-67
lines changed

Docs/tutorial-config.md

Lines changed: 220 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,271 @@
11
---
2-
title: '👉 09 TypeScript 配置使用'
3-
excerpt: 'Next.js 提供了 TypeScript 集成体验,通过配置 TypeScript,即可以转换 JavaScript 开发环境,以使用 Next.js 的类型规范。'
2+
title: '👉 09 next.config.js 配置脚本'
3+
excerpt: 'Next.js 在顶级目录下提供了 next.config.js 配置脚本,可以随时建立这个配置文件'
44
coverImage: '/20161106s.jpg'
5-
date: '2021-02-05T01:49:07.322Z'
5+
date: '2021-02-05T02:10:07.322Z'
66
author:
77
name: Jeango
88
picture: '/jeango.jpg'
99
ogImage:
1010
url: '/20161106s.jpg'
1111
---
1212

13-
# 👉 Next.js with TypeScript
13+
# 👉 next.config.js 配置脚本
14+
- https://nextjs.org/docs/api-reference/next.config.js
15+
- https://en.wikipedia.org/wiki/Content_delivery_network
1416

15-
- https://nextjs.org/learn/excel/typescript
16-
- https://nextjs.org/docs/basic-features/typescript
17-
- https://github.com/vercel/next.js/tree/canary/examples/with-typescript
18-
- https://github.com/vercel/next-learn-starter/tree/master/typescript-final
17+
环境变量配置:
1918

20-
Next.js 提供了 TypeScript 集成体验,通过配置 TypeScript,即可以转换 JavaScript 开发环境,以使用 Next.js 的类型规范。
19+
```js
20+
module.exports = {
21+
env: {
22+
customKey: 'my-value',
23+
},
24+
}
25+
```
2126

22-
首先安装 TypeScript 编译器和相关的类型声明模块,Node.js 模块本身已经含有类型声明文件,不用另外安装。
27+
使用环境变量:
2328

24-
然后一并在工程目录中初始化默认配置文件 `tsconfig.json`,TypeScript strict 模式默认是没有开启的,建议打开。ts-node 模块可以用来直接运行 ts 脚本:
29+
```js
30+
function Page() {
31+
return <h1>The value of customKey is: {process.env.customKey}</h1>
32+
}
2533

26-
npm install -g typescript
27-
npm install -g ts-node
28-
tsc --init
34+
export default Page
2935

30-
# If you’re using npm
31-
npm install --save-dev typescript @types/react @types/node
36+
```
3237

33-
# If you’re using Yarn
34-
yarn add --dev typescript @types/react @types/node
3538

39+
要将应用配置在子目录中运行,请使用 basePath 指定。
3640

37-
编译器会生成 `next-env.d.ts` 这个类型声明模块文件,检查它可以确定 Next.js 类型已经在 TypeScript 编译器中起作用,通常内容是使用三斜杠指令引用其它的类型声明模块:
41+
```js
42+
module.exports = {
43+
basePath: '/docs',
44+
}
45+
```
3846

39-
/// <reference types="next" />
40-
/// <reference types="next/types/global" />
47+
在使用 `next/link``next/router` 组件的情况下,`basePath` 设置会自动更新。比如以下例子的 `/about` 会自动更新为`/docs/about`
4148

49+
```ts
50+
export default function HomePage() {
51+
return (
52+
<>
53+
<Link href="/about">
54+
<a>About Page</a>
55+
</Link>
56+
</>
57+
)
58+
}
59+
```
4260

43-
然后重启开发服务器,以使用 TypeScript 功能生效
61+
但是图片这些就不是了
4462

45-
Next.js Specific Types 提供的类型如下。
4663

47-
Static Generation and Server-side Rendering
64+
为 CDN 配置资源的路径前缀:
4865

49-
```ts
50-
import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'
66+
```js
67+
const isProd = process.env.NODE_ENV === 'production'
5168

52-
export const getStaticProps: GetStaticProps = async context => {
53-
// ...
69+
module.exports = {
70+
// Use the CDN in production and localhost for development.
71+
assetPrefix: isProd ? 'https://cdn.mydomain.com' : '',
5472
}
73+
```
74+
75+
Next.js 会自动为 JavaScript 和 CSS 文件的加载使用 `/_next/` 路径前缀,即指向 `.next/static/` 目录下的内容。
76+
77+
配置资源路径前缀并不影响以下路径:
78+
79+
- `/public` 目录,这里的文件如果要配置 CDN 就要自行处理。
80+
- `/_next/data/` 下由 `getServerSideProps()` 请求的页面,因为它们不是静态内容。
81+
- `/_next/data/` 下由 `getStaticProps()` 请求的页面,这些是为主域和增量静态生成使用。
82+
5583

56-
export const getStaticPaths: GetStaticPaths = async () => {
57-
// ...
84+
配置构建输出目录:
85+
86+
```js
87+
module.exports = {
88+
distDir: 'build',
5889
}
90+
```
91+
92+
配置扩展名支持,包括 `next/mdx` 文档增强插件,MDX 让 Markdown 步入组件时代 MDX 是一种书写格式,允许在文档中无缝地插入 JSX 代码。
5993

60-
export const getServerSideProps: GetServerSideProps = async context => {
61-
// ...
94+
```js
95+
module.exports = {
96+
pageExtensions: ['mdx', 'jsx', 'js', 'ts', 'tsx'],
6297
}
6398
```
6499

65-
API Routes
100+
配置请请求头处理,支持 i18n 国际化:
101+
102+
```js
103+
module.exports = {
104+
i18n: {
105+
locales: ['en', 'fr', 'de'],
106+
defaultLocale: 'en',
107+
},
108+
109+
async headers() {
110+
return [
111+
{
112+
// does not handle locales automatically since locale: false is set
113+
source: '/nl/with-locale-manual',
114+
locale: false,
115+
headers: [
116+
{
117+
key: 'x-hello',
118+
value: 'world',
119+
},
120+
],
121+
},
122+
{
123+
// this matches '/' since `en` is the defaultLocale
124+
source: '/en',
125+
locale: false,
126+
headers: [
127+
{
128+
key: 'x-hello',
129+
value: 'world',
130+
},
131+
],
132+
},
133+
{
134+
source: '/blog/:post(\\d{1,})',
135+
headers: [
136+
{
137+
key: 'x-post',
138+
value: ':post',
139+
},
140+
],
141+
},
142+
],
143+
},
144+
}
145+
```
66146

67-
```ts
68-
import { NextApiRequest, NextApiResponse } from 'next'
147+
地址重写配置 URL Rewrites:
148+
149+
```js
150+
module.exports = {
151+
basePath: '/docs',
152+
i18n: {
153+
locales: ['en', 'fr', 'de'],
154+
defaultLocale: 'en',
155+
},
156+
157+
async rewrites() {
158+
return [
159+
{
160+
source: '/with-basePath', // automatically becomes /docs/with-basePath
161+
destination: '/another', // automatically becomes /docs/another
162+
},
163+
{
164+
// does not add /docs to /without-basePath since basePath: false is set
165+
// Note: this can not be used for internal rewrites e.g. `destination: '/another'`
166+
source: '/without-basePath',
167+
destination: 'https://example.com',
168+
basePath: false,
169+
},
170+
{
171+
// does not handle locales automatically since locale: false is set
172+
source: '/nl/with-locale-manual',
173+
destination: '/nl/another',
174+
locale: false,
175+
},
176+
]
177+
},
178+
}
179+
```
69180

70-
export default (req: NextApiRequest, res: NextApiResponse) => {
71-
// ...
181+
重定向配置:
182+
183+
```js
184+
module.exports = {
185+
basePath: '/docs',
186+
i18n: {
187+
locales: ['en', 'fr', 'de'],
188+
defaultLocale: 'en',
189+
},
190+
191+
async redirects() {
192+
return [
193+
{
194+
// this matches '/' since `en` is the defaultLocale
195+
source: '/en',
196+
destination: '/en/another',
197+
locale: false,
198+
permanent: false,
199+
},
200+
{
201+
source: '/post/:slug(\\d{1,})',
202+
destination: '/news/:slug', // Matched parameters can be used in the destination
203+
permanent: false,
204+
},
205+
{
206+
source: '/with-basePath', // automatically becomes /docs/with-basePath
207+
destination: '/another', // automatically becomes /docs/another
208+
permanent: false,
209+
},
210+
{
211+
// does not add /docs since basePath: false is set
212+
source: '/without-basePath',
213+
destination: '/another',
214+
basePath: false,
215+
permanent: false,
216+
},
217+
]
218+
},
72219
}
73220
```
74221

75-
接下来需要将 JavaScript 工程的脚本文件改成 TypeScript,例如可以将 `pages/_app.js` 转换为 .tsx 扩展名以使用 AppProps 类型:
76222

77-
```ts
78-
import { AppProps } from 'next/app'
79223

80-
function App({ Component, pageProps }: AppProps) {
81-
return <Component {...pageProps} />
224+
配置 Webpack:
225+
226+
```js
227+
// Example config for adding a loader that depends on babel-loader
228+
// This source was taken from the @next/mdx plugin source:
229+
// https://github.com/vercel/next.js/tree/canary/packages/next-mdx
230+
module.exports = {
231+
webpack: (config, options) => {
232+
config.module.rules.push({
233+
test: /\.mdx/,
234+
use: [
235+
options.defaultLoaders.babel,
236+
{
237+
loader: '@mdx-js/loader',
238+
options: pluginOptions.options,
239+
},
240+
],
241+
})
242+
243+
return config
244+
},
82245
}
83-
84-
export default App
85246
```
86247

87-
列如,布局模块可以更新为带 TypeScript 类型语法结构:
248+
```js
249+
module.exports = {
250+
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
251+
// Note: we provide webpack above so you should not `require` it
252+
// Perform customizations to webpack config
253+
config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
88254

89-
```ts
90-
export default function Layout({
91-
children,
92-
home
93-
}: {
94-
children: React.ReactNode
95-
home?: boolean
96-
}) {
97-
return (<>...<>)
255+
// Important: return the modified config
256+
return config
257+
},
98258
}
99259
```
100260

101-
转换后的文件可以参考 next-learn-starter 的 typescript-final
102261

103-
使用静态类型语法后,在 VSCode 中会有更多的提示信息,需要认真理解提示的意义。
104262

105-
例如,以下代码中的返回值会给出错误信息:
106263

107-
```ts
108-
export default function App({ Component, pageProps }):AppProps {
109-
return (
110-
<><Component {...pageProps} /></>
111-
)
264+
配置 React Strict Mode
265+
266+
```js
267+
// next.config.js
268+
module.exports = {
269+
reactStrictMode: true,
112270
}
113271
```
114-
115-
乍一看,是正确 tsx 语法,但是,仔细分析一下函数 AppProps 变成了函数的返回值,导致改变了函数签名而引发错误:
116-
117-
Type 'Element' is not assignable to type 'AppPropsType<Router, {}>'.
118-
Property 'pageProps' is missing in type 'Element' but required in type 'AppInitialProps'.ts(2322)

0 commit comments

Comments
 (0)