diff --git a/404.html b/404.html index d07a4c0bd..940f4d6e6 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -
© Musher 2019 - 2024
powered by nobelium
© Musher 2019 - 2024
powered by nobelium
/** @type {import('next').NextConfig} */
+ 引言
前段时间入坑了 React 开发,学习了基本语法后就决定找个项目跟着写写,由于b站上相关的资源重复率实在是太高了,我实在不想再写一个苍穹外卖之类的东西,于是在 YouTube 上找到了该视频,该项目是一个作品集项目,我觉得作为我 React 的 startup 非常不错,而且这个网页的审美也很合我的品味。本着 up 敲一行我就敲一行的学习精神,两个半小时的项目也不难敲,最后项目上线的时候该博主使用 Vercel 进行部署,本着能省一点是一点的原则,我决定使用 Github Page 功能进行部署,主要原因如下- 免费,真的良心
- 本来这东西就是静态的,没什么后端服务,我想着给他渲染成纯静态页面丢上去不就完了呗
于是,开搞!困境

首先,我遇到了第一个问题,部署页面有两种方式,我到底该使用 Github Action 方式,还是 Deploy from a branch 方式?网上介绍的大多是第二种方式,这里笔者推荐使用第一种方式,我们可以看到这两种方式配置好之后的工作流是什么样的,孰优孰劣大家自有评判Github Action 方式
以 main 分支为当前分支为例,只需要将当前 commit push 上去→触发 Github Action,直接完成 page 更新。Deploy from a branch 方式
本地修改后,在本地进行编译→使用 gh-pages 将编译结果推送到 gh-pages 分支,完成更新,相比于前一种方式,除了修改代码,还需要手动编译,再推送,非常不优雅。
关于如何使用 Github Action 方式进行部署,选中该方式之后,github 会弹一个工作流文件出来,检测到当前项目为 Nextjs 项目后会自动推荐 Nextjs 的工作流,我们可以暂时先用这个工作流,后面再进行修改。此时按理来说,只要你没有使用什么在服务端不可用的生命周期钩子,你的代码会顺利在 Github 的服务器上完成编译,并成为该项目的 Page,但事情并没有这么简单。静态资源路径问题
当我第一次看到 Github Action 中的工作流中,编译成功的绿标出现后,我非常兴奋的打开了我的网页,它长这样:
这是我直接打开本地编译的结果,仅作演示 坑爹呢这是 😵💫,此时打开开发者工具发现,除了当前页面的 html 外,不论是处于_next/static
路径下的静态资源(主要是js和css),还是处于public
路径下的静态资源(主要是图片),资源路径通通是错的,这个项目的路径应该是musherm.github.io/Portofolio/
,但所有的资源都指向musherm.github.io/
,换言之,我需要给所有的静态资源路径前面加上一个’Portofolio/’
,查阅官方文档,我们可以发现,nextjs.config.mjs这一文件中,存在两个选项与路径有关,他们分别是:basePath
该选项用于在一个子路径下部署项目,他主要在两种场景下生效:- Links:当使用
next/link
和next/router
时,会自动添加basePath,也就是说<Link href="/about">About Page</Link>
会输出<a href="/docs/about">About Page</a>
(basePath=’/docs’
)
- Image:当使用
next/image
时,需要手动添加basePath,说白了就是不管你引用图片用的是<img>
还是<Image>
,你通通需要手动把这个路径写完整
官方既然考虑到了图片资源会出现这个问题,为啥不能通过 basePath 自动给他加上呢,无语了。assetPrefix
该选项仅针对_next/static
下的静态js css资源,不会影响public下的资源,看来这一选项可以帮助我们解决js和css找不到的问题!修改我们的nextconfig
为这样:/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: "export",
+ basePath: "/Portofolio",
+ assetPrefix: "/Portofolio/",
+ images: {
+ unoptimized: true,
+ },
+};
+
+export default nextConfig;
好,至少我们的js和css确实找到了,但是事情还没有解决,我们的img标签下的所有图片,无一例外,还是指向了根目录,根据官方文档,你必须手动给他加上。比如一个img
标签,你修改之前它长这样:<img
+ src={icon}
+ alt={icon}
+ className="p-2"
+/>
修改之后呢,它应该长这样:<img
+ src={
+ process.env.NEXT_PUBLIC_ASSET_PREFIX + icon
+ }
+ alt={icon}
+ className="p-2"
+/>
同时修改你的nextconfig
,提供一下NEXT_PUBLIC_ASSET_PREFIX
这个环境变量,当然,你也可以通过.env .env.local 来提供,但我不喜欢把配置文件分散在好几个文件上,尽量集中管理比较清晰:/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: "export",
+ basePath: "/Portofolio",
+ assetPrefix: "/Portofolio/",
+ images: {
+ unoptimized: true,
+ },
+ env: {
+ NEXT_PUBLIC_ASSET_PREFIX: "/Portofolio",
+ },
+};
+
+export default nextConfig;
到这里,你在编译的代码如果直接打开,资源路径应该已经加上了你的相对路径名,如果直接 push 上去,Github Action 部署还是会不成功,因为服务器端并不会读取你在 nextconfig 里定义的环境变量,你还需要在工作流中提供这个环境变量,所幸这个操作其实也很简单:打开用于定义工作流的文件,在我的环境下是.github/workflows/nextjs.yml,并在编译的时候提供环境变量,比如这样- name: Build with Next.js
+ run: ${{ steps.detect-package-manager.outputs.runner }} next build
+ # Add this
+ env:
+ NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
添加的这一行,会在服务器端编译的过程中提供这个环境变量,从而保证编译后对于public文件夹下的静态资源访问正确,到这里,我们就已经完成了对于 Nextjs 项目的 Github Page 部署。后谈
细心的小伙伴可能发现,写死 basePath
assetPrefix
NEXT_PUBLIC_ASSET_PREFIX
这些变量,当你在本地dev环境开发时,你的首页会从localhost:3000
变成localhost:3000/Portofolio
,如果你能接受,那其实也还行,但如果想“不行,我在本地开发的时候,我就要在localhost:3000
直接访问
+!”那你可以继续看下去(没错,说的就是我自己,我真的忍受不了每次从终端点开这个链接,还需要手动补全后面的路径)。答案是,你可以像NEXT_PUBLIC_ASSET_PREFIX
一样,再引入一个NODE_ENV
来判断当前的开发环境,从而在生产环境使用子路径,但在开发环境不实用,此时nextconfig
修改如下:/** @type {import('next').NextConfig} */
const isProd = process.env.NODE_ENV === "production";
const nextConfig = {
output: "export",
@@ -29,18 +103,17 @@
},
};
-export default nextConfig;
部署项目的过程中出现的问题:对于public文件夹中的静态资源,可以直接通过/1.png
访问,但编译后的/1.png
,将直接指向根目录,在本地这是C://
,在github page这是musherm.github.io/
,但实际上的静态资源地址在musherm.github.io/Portofolio
,该如何正确指向该地址?// icon='/b1.svg'
-<img
- src={
- (process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + icon
- }
- alt={icon}
- className="p-2"
-/>
答案是使用process.env.NEXT_PUBLIC_ASSET_PREFIX
这个环境变量,在github action编译时,通过修改Build过程时的环境变量指定环境为production,使NEXT_PUBLIC_ASSET_PREFIX
这个环境变量变为/Portofolio
,从而指向正确的地址- name: Build with Next.js
+export default nextConfig;
同时修改img
标签的src
如下<img src={
+ (process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + "/profile.svg"
+ }
+ alt="profile"
+/>
你可能想问为什么?按理来说我在dev环境已经指定了NEXT_PUBLIC_ASSET_PREFIX
为空啊?这就是Nextjs
的又一大坑,Nextjs
的环境变量无法指定为空!(至少据我所知)如果你像这样试图指定为空,它会变成undefined
,因而你需要通过(process.env.NEXT_PUBLIC_ASSET_PREFIX || "")
这样的表达式体操来让undefined
变成真正的空。此外,你还需要修改 Github Action 的流程定义文件,从而指定编译环境为 production
。- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
env:
NODE_ENV: production
- NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
一些环境体操
- 为什么需要使用
(process.env.NEXT_PUBLIC_ASSET_PREFIX || "")
,而不是在dev环境下将NEXT_PUBLIC_ASSET_PREFIX
这个变量设为空?因为根据我的观察,只要你试图把一个环境变量设为空,他就会变成undefined
,所以干脆就这么写了
- 这个basePath也是,他只会更改你的项目的基本地址,不会自动更改你的静态资源的路径,也就是说如果把basePath设为
/Portofolio
,你本地的开发环境地址就会从127.0.0.1:3000变成127.0.0.1:3000/Portofolio,
- assetPrefix也是同理,没什么卵用,听起来像是能给你的静态资源加个前缀,但是没用
关于basePath和assetPrefix
basePath
该选项用于在一个子路径下部署项目,他主要在两种场景下生效:- Links:当使用
next/link
和next/router
时,会自动添加basePath,也就是说<Link href="/about">About Page</Link>
会输出<a href="/docs/about">About Page</a>
(basePath=’/docs’
)
- Image:当使用
next/image
时,需要手动添加basePath,就像我做的那样
assetPrefix
该选项仅针对_next/static
下的静态js css资源,不会影响public下的资源,当然,这个选项还是要设的,不然可能css和js也会因为指向根目录而找不到可能的另一种方式:自定义ImageLoader
使用next/image
时,可以通过自定义imageloader的方式,使用一个函数来返回对应的路径,这个函数就可以对src进行路径拼接等处理,以避免出现(process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + icon
这样不优雅的代码 ]]>
+ NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
basePath
assetPrefix
NEXT_PUBLIC_ASSET_PREFIX
三兄弟,完成了对css
js
img
这些静态资源的路径补全;image loader
:export default function myImageLoader({ src, width, quality }) {
+ return `https://example.com/${src}?w=${width}&q=${quality || 75}`
+}
/** @type {import('next').NextConfig} */
+Next.js 踩坑记(1)——路径体操 😶🌫️ Next.js 踩坑记(1)——路径体操
dateMay 29, 2024slugpath-middlestatusPublishedtagsReactNext.jsWebsitesummary如何愉快的将你的 Nextjs 项目部署上 Github Page?typePost引言
前段时间入坑了 React 开发,学习了基本语法后就决定找个项目跟着写写,由于b站上相关的资源重复率实在是太高了,我实在不想再写一个苍穹外卖之类的东西,于是在 YouTube 上找到了该视频,该项目是一个作品集项目,我觉得作为我 React 的 startup 非常不错,而且这个网页的审美也很合我的品味。本着 up 敲一行我就敲一行的学习精神,两个半小时的项目也不难敲,最后项目上线的时候该博主使用 Vercel 进行部署,本着能省一点是一点的原则,我决定使用 Github Page 功能进行部署,主要原因如下- 免费,真的良心
- 本来这东西就是静态的,没什么后端服务,我想着给他渲染成纯静态页面丢上去不就完了呗
于是,开搞!困境

首先,我遇到了第一个问题,部署页面有两种方式,我到底该使用 Github Action 方式,还是 Deploy from a branch 方式?网上介绍的大多是第二种方式,这里笔者推荐使用第一种方式,我们可以看到这两种方式配置好之后的工作流是什么样的,孰优孰劣大家自有评判Github Action 方式
以 main 分支为当前分支为例,只需要将当前 commit push 上去→触发 Github Action,直接完成 page 更新。Deploy from a branch 方式
本地修改后,在本地进行编译→使用 gh-pages 将编译结果推送到 gh-pages 分支,完成更新,相比于前一种方式,除了修改代码,还需要手动编译,再推送,非常不优雅。
关于如何使用 Github Action 方式进行部署,选中该方式之后,github 会弹一个工作流文件出来,检测到当前项目为 Nextjs 项目后会自动推荐 Nextjs 的工作流,我们可以暂时先用这个工作流,后面再进行修改。此时按理来说,只要你没有使用什么在服务端不可用的生命周期钩子,你的代码会顺利在 Github 的服务器上完成编译,并成为该项目的 Page,但事情并没有这么简单。静态资源路径问题
当我第一次看到 Github Action 中的工作流中,编译成功的绿标出现后,我非常兴奋的打开了我的网页,它长这样:
这是我直接打开本地编译的结果,仅作演示 坑爹呢这是 😵💫,此时打开开发者工具发现,除了当前页面的 html 外,不论是处于_next/static
路径下的静态资源(主要是js和css),还是处于public
路径下的静态资源(主要是图片),资源路径通通是错的,这个项目的路径应该是musherm.github.io/Portofolio/
,但所有的资源都指向musherm.github.io/
,换言之,我需要给所有的静态资源路径前面加上一个’Portofolio/’
,查阅官方文档,我们可以发现,nextjs.config.mjs这一文件中,存在两个选项与路径有关,他们分别是:basePath
该选项用于在一个子路径下部署项目,他主要在两种场景下生效:- Links:当使用
next/link
和next/router
时,会自动添加basePath,也就是说<Link href="/about">About Page</Link>
会输出<a href="/docs/about">About Page</a>
(basePath=’/docs’
)
- Image:当使用
next/image
时,需要手动添加basePath,说白了就是不管你引用图片用的是<img>
还是<Image>
,你通通需要手动把这个路径写完整
官方既然考虑到了图片资源会出现这个问题,为啥不能通过 basePath 自动给他加上呢,无语了。assetPrefix
该选项仅针对_next/static
下的静态js css资源,不会影响public下的资源,看来这一选项可以帮助我们解决js和css找不到的问题!修改我们的nextconfig
为这样:/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: "export",
+ basePath: "/Portofolio",
+ assetPrefix: "/Portofolio/",
+ images: {
+ unoptimized: true,
+ },
+};
+
+export default nextConfig;
好,至少我们的js和css确实找到了,但是事情还没有解决,我们的img标签下的所有图片,无一例外,还是指向了根目录,根据官方文档,你必须手动给他加上。比如一个img
标签,你修改之前它长这样:<img
+ src={icon}
+ alt={icon}
+ className="p-2"
+/>
修改之后呢,它应该长这样:<img
+ src={
+ process.env.NEXT_PUBLIC_ASSET_PREFIX + icon
+ }
+ alt={icon}
+ className="p-2"
+/>
同时修改你的nextconfig
,提供一下NEXT_PUBLIC_ASSET_PREFIX
这个环境变量,当然,你也可以通过.env .env.local 来提供,但我不喜欢把配置文件分散在好几个文件上,尽量集中管理比较清晰:/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: "export",
+ basePath: "/Portofolio",
+ assetPrefix: "/Portofolio/",
+ images: {
+ unoptimized: true,
+ },
+ env: {
+ NEXT_PUBLIC_ASSET_PREFIX: "/Portofolio",
+ },
+};
+
+export default nextConfig;
到这里,你在编译的代码如果直接打开,资源路径应该已经加上了你的相对路径名,如果直接 push 上去,Github Action 部署还是会不成功,因为服务器端并不会读取你在 nextconfig 里定义的环境变量,你还需要在工作流中提供这个环境变量,所幸这个操作其实也很简单:打开用于定义工作流的文件,在我的环境下是.github/workflows/nextjs.yml,并在编译的时候提供环境变量,比如这样- name: Build with Next.js
+ run: ${{ steps.detect-package-manager.outputs.runner }} next build
+ # Add this
+ env:
+ NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
添加的这一行,会在服务器端编译的过程中提供这个环境变量,从而保证编译后对于public文件夹下的静态资源访问正确,到这里,我们就已经完成了对于 Nextjs 项目的 Github Page 部署。后谈
细心的小伙伴可能发现,写死 basePath
assetPrefix
NEXT_PUBLIC_ASSET_PREFIX
这些变量,当你在本地dev环境开发时,你的首页会从localhost:3000
变成localhost:3000/Portofolio
,如果你能接受,那其实也还行,但如果想“不行,我在本地开发的时候,我就要在localhost:3000
直接访问
+!”那你可以继续看下去(没错,说的就是我自己,我真的忍受不了每次从终端点开这个链接,还需要手动补全后面的路径)。答案是,你可以像NEXT_PUBLIC_ASSET_PREFIX
一样,再引入一个NODE_ENV
来判断当前的开发环境,从而在生产环境使用子路径,但在开发环境不实用,此时nextconfig
修改如下:/** @type {import('next').NextConfig} */
const isProd = process.env.NODE_ENV === "production";
const nextConfig = {
output: "export",
@@ -12,15 +86,14 @@
},
};
-export default nextConfig;
部署项目的过程中出现的问题:对于public文件夹中的静态资源,可以直接通过/1.png
访问,但编译后的/1.png
,将直接指向根目录,在本地这是C://
,在github page这是musherm.github.io/
,但实际上的静态资源地址在musherm.github.io/Portofolio
,该如何正确指向该地址?// icon='/b1.svg'
-<img
- src={
- (process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + icon
- }
- alt={icon}
- className="p-2"
-/>
答案是使用process.env.NEXT_PUBLIC_ASSET_PREFIX
这个环境变量,在github action编译时,通过修改Build过程时的环境变量指定环境为production,使NEXT_PUBLIC_ASSET_PREFIX
这个环境变量变为/Portofolio
,从而指向正确的地址- name: Build with Next.js
+export default nextConfig;
同时修改img
标签的src
如下<img src={
+ (process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + "/profile.svg"
+ }
+ alt="profile"
+/>
你可能想问为什么?按理来说我在dev环境已经指定了NEXT_PUBLIC_ASSET_PREFIX
为空啊?这就是Nextjs
的又一大坑,Nextjs
的环境变量无法指定为空!(至少据我所知)如果你像这样试图指定为空,它会变成undefined
,因而你需要通过(process.env.NEXT_PUBLIC_ASSET_PREFIX || "")
这样的表达式体操来让undefined
变成真正的空。此外,你还需要修改 Github Action 的流程定义文件,从而指定编译环境为 production
。- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
env:
NODE_ENV: production
- NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
一些环境体操
- 为什么需要使用
(process.env.NEXT_PUBLIC_ASSET_PREFIX || "")
,而不是在dev环境下将NEXT_PUBLIC_ASSET_PREFIX
这个变量设为空?因为根据我的观察,只要你试图把一个环境变量设为空,他就会变成undefined
,所以干脆就这么写了
- 这个basePath也是,他只会更改你的项目的基本地址,不会自动更改你的静态资源的路径,也就是说如果把basePath设为
/Portofolio
,你本地的开发环境地址就会从127.0.0.1:3000变成127.0.0.1:3000/Portofolio,
- assetPrefix也是同理,没什么卵用,听起来像是能给你的静态资源加个前缀,但是没用
关于basePath和assetPrefix
basePath
该选项用于在一个子路径下部署项目,他主要在两种场景下生效:- Links:当使用
next/link
和next/router
时,会自动添加basePath,也就是说<Link href="/about">About Page</Link>
会输出<a href="/docs/about">About Page</a>
(basePath=’/docs’
)
- Image:当使用
next/image
时,需要手动添加basePath,就像我做的那样
assetPrefix
该选项仅针对_next/static
下的静态js css资源,不会影响public下的资源,当然,这个选项还是要设的,不然可能css和js也会因为指向根目录而找不到可能的另一种方式:自定义ImageLoader
使用next/image
时,可以通过自定义imageloader的方式,使用一个函数来返回对应的路径,这个函数就可以对src进行路径拼接等处理,以避免出现(process.env.NEXT_PUBLIC_ASSET_PREFIX || "") + icon
这样不优雅的代码
© Musher 2019 - 2024
powered by nobelium
\ No newline at end of file
+ NEXT_PUBLIC_ASSET_PREFIX: /Portofolio
basePath
assetPrefix
NEXT_PUBLIC_ASSET_PREFIX
三兄弟,完成了对css
js
img
这些静态资源的路径补全;image loader
:export default function myImageLoader({ src, width, quality }) {
+ return `https://example.com/${src}?w=${width}&q=${quality || 75}`
+}
© Musher 2019 - 2024
powered by nobelium