NextJS 部署到特定的 URL 路径

se2*_*2as 7 reactjs next.js

我正在开发我的第一个 NextJS 应用程序。当我运行“npm run dev”或“npm run start”时,它会将我的应用程序部署到

http://host:port/
Run Code Online (Sandbox Code Playgroud)

当我导航到一个页面时,网址变为

http://host:port/page1
Run Code Online (Sandbox Code Playgroud)

我需要有自己的特定网址,例如

http://host:port/my-test-application/path-for-my-app/
http://host:port/my-test-application/path-for-my-app/page1
Run Code Online (Sandbox Code Playgroud)

此外,我的应用程序有很多元素可以链接到应用程序的其他区域,我需要这些元素也可以使用 basePath 转到 URL 而不仅仅是转到根路径。

我还将将此应用程序部署到具有不同 basePath 的不同服务器,因此无法在我的应用程序中进行硬编码。

我怎样才能做到这一点?

对于其他应用程序,例如 react/vue/angular/native JS,我只需构建我的应用程序并将构建代码放在我的服务器上的“my-test-application/path-for-my-app”文件夹中。

我用我的 NextJS 应用程序尝试过这个,但我收到一个错误,说找不到“.next”文件夹。

我用谷歌搜索,可以找到一些使用“assetPrefix”或使用“Zones”的参考。但是,我真的不明白我应该做什么。

如何将我的应用程序部署到特定 URL

解决方案 1:重组“页面” - 无法部署到具有不同 basePaths 的不同服务器

我可以在“pages”目录中创建文件夹结构并更改我的所有元素以使用此文件夹结构。

|- pages
     |- my-test-application
           |- path-for-my-app
                |- index.js
                |- page1.js


<Link href="/my-test-application/path-for-my-app/page1" >
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个解决方案,因为 basePath 被硬编码到我的应用程序中,与部署设置相关。

如果我想将我的应用程序部署在具有不同 basePaths(即下面)的 2 个服务器上,我将必须有 2 个版本的代码。

http://host:port/my-test-application_1/path-for-my-app/page1
http://host:port/my-test-application_2/diff-path-for-my-app/page1
Run Code Online (Sandbox Code Playgroud)

更新:我在 3 月 5 日更新了这个问题,包括我对 s 工作的需求和我不喜欢的一个解决方案。

Luk*_*lor 15

在 Next.js 中?9.5、你可以basePath在你的next.config.js. 例如,如果您希望整个 Next.js 应用程序都位于/docs,则可以使用:

// next.config.js
module.exports = {
  basePath: '/docs'
}
Run Code Online (Sandbox Code Playgroud)

Next 将确保所有资产都从正确的位置提供,并且它会自动为Link您的应用程序中的所有s加上此基本路径的前缀,以及在使用next/router. 例如,

<Link href="/about">
  <a>About Page</a>
</Link>
Run Code Online (Sandbox Code Playgroud)

将被改造链接/docs/about,如意志

<Link href="/about">
  <a>About Page</a>
</Link>
Run Code Online (Sandbox Code Playgroud)

这意味着您可以basePath在不更改应用程序实际代码中的任何内容的情况下进行更改。


se2*_*2as 5

我找到了一个使用 NGINX 反向代理带有基本路径的 URL 的解决方案。

有用的链接

应用程序更改

依赖关系

  • next-images :为了在使用反向代理时从“public”导入静态图像
  • @zeit/next-css :为了使用样式表文件
  • 以及通常的 NextJS 依赖项

下一个.config.js

在应用程序的根目录添加“next.config.js”文件,以便您可以指定“assetPrefix”和“publicRuntimeConfig.basePath”

  • assetPrefix : NextJS 在访问组件、样式表、页面等时使用
  • publicRuntimeConfig.basePath : 用于 s so 指定要添加到链接的前缀,在使用公共图片时用于 "" 元素的 "src" 标签

例子

const isProd = process.env.NODE_ENV === 'production'

// Enable importing of css stylesheets
const withCSS = require("@zeit/next-css");
const withImages = require('next-images');

/*
 * Gets the BASE_PATH from the command used to start this app.
 * If BASE_PATH is specified but it does not start with a "/" 
 * then add it. 
 */
function getBasePath() {
    var basePath = ''

    if (isProd && process.env.BASE_PATH){
        if (process.env.BASE_PATH.startsWith("/") ){
            basePath = process.env.BASE_PATH;
        } else {
            basePath = "/" + process.env.BASE_PATH;
        }
    } 

    console.log("getBasePath() : isProd = " + isProd);
    console.log("getBasePath() : basePath = " + basePath);

    return basePath
}

module.exports = withCSS(withImages({
    assetPrefix: getBasePath() ,

    publicRuntimeConfig: {
        basePath: getBasePath() ,
    },

}));
Run Code Online (Sandbox Code Playgroud)

静态图片

使用“next-images”来导入图像并在 的 src 标签中引用导入的对象

更改对静态图像(/public 文件夹中的那些)的任何引用以具有基本路径前缀。例如,我的“页脚”组件具有以下内容

import '../stylesheets/main.css';

import img1 from '../public/image_name1.png'
import img2 from '../public/image_name2.png'

export default class o extends React.Component {

    render(){
        var prefix = publicRuntimeConfig.basePath
        return  (
            <div >
                <a className="icon" href="http://www.image_name.com" >
                    <img src={img1} alt="image_name1"/>
                </a>
                <a className="icon" href="http://www.image_name2.com">
                    <img  src={img1} alt="image_name2"/>
                </a>
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我尝试使用 publicRuntimeConfig.basePath 作为 src URL 的前缀(如下所示),但这在我部署的环境中不起作用(见下文)

    import getConfig from 'next/config'
    const { publicRuntimeConfig } = getConfig()
    ...
    ...
    <a className="icon" href="http://www.image_name.com" >
        <img src={`${publicRuntimeConfig.basePath}/image_name1.png`} alt="image_name1"/>
    </a>
Run Code Online (Sandbox Code Playgroud)

链接

更改您的链接以使用基本路径前缀,例如在我的“标题”组件中,我有以下内容

import Link from 'next/link';
import '../stylesheets/main.css';

import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig()

const detailId1 = "banana"

const Header = () => (
    <div>
        <div>
            <Link href={`${publicRuntimeConfig.basePath || ''}/`}>
                <a className="linkStyle">Home</a>
            </Link>

            <Link href={`${publicRuntimeConfig.basePath || ''}/about`} >
                <a className="linkStyle">About</a>
            </Link>

            <Link href={`${publicRuntimeConfig.basePath || ''}/details/[id]`} 
                  as= {`${publicRuntimeConfig.basePath || ''}/details/${detailId1}`} >
                <a className="linkStyle">Details Var 1</a>
            </Link>
        </div>
  </div>
);

export default Header;
Run Code Online (Sandbox Code Playgroud)

注意:在博客https://levelup.gitconnected.com/deploy-your-nextjs-application-on-a-different-base-path-ie-not-root-1c4d210cce8a 中,它包含一个“Link.tsx”为您添加前缀,因此您只需使用该 Link 组件(从“./Link.tsx”导入链接;)而不是 nextJS 版本(从“next/link”导入链接;)。但是,当我的链接 URL 中有变量时,“Link.tsx”对我不起作用。

运行你的 nextjs 应用

当您不想要基本路径时,在本地运行您的应用程序时,您可以只运行

npm run dev
Run Code Online (Sandbox Code Playgroud)

由于未指定 BASE_PATH,您的应用程序应该可以从“ http://localhost:3000 ”访问,您的 src 值应该是“/image_name1.png”,当您将鼠标悬停在 s 上时,您将看到链接是“ http://本地主机:3000/页面名称

当您想使用基本路径运行时,请执行以下操作

export BASE_PATH=a/b
npm run dev
Run Code Online (Sandbox Code Playgroud)

注意:出于某种原因,在我的环境中,如果我指定“export BASE_PATH=/a/b”(/ 在路径的开头),我会在路径的开头添加一个文件夹目录。因此我指定它没有起始 / 并且 next.config.js 中的代码添加起始 / 如果需要。

您无法通过“ http://localhost:3000 ”访问您的应用程序,因为您设置了基本路径/assetPrefix/publicRuntimeConfig.basePath。现在你需要一个反向代理。

NGINX:反向代理

我发现最简单的设置是使用 NGINX docker 镜像。您需要使用包含重定向到 NextJS 应用程序的配置来运行 NGINX。

创建一个文件夹并在该文件夹中添加一个“default.conf”文件。确保您在“位置”中放置的路径与您在启动 nextjs 应用程序时为 BASE_PATH 指定的路径相同。

server {
    listen 80;
    server_name  localhost;

    location /a/b/ {
        proxy_pass http://myhost:3000/;
    }       
}
Run Code Online (Sandbox Code Playgroud)

重要笔记:

  • 你必须在你的 proxy_pass URL 的末尾加上 / 否则额外的路径不会传递到你的 NextJS 应用程序中
  • 如果在该位置使用变量,则必须确保包含传递路径

例子

location ~ /a/b/(.*)$ {  
    set $upstream http://myhost:3000/$1;
    proxy_pass $upstream;
}
Run Code Online (Sandbox Code Playgroud)

在该目录的命令提示符下运行 NGINX docker 映像,告诉它使用您的配置文件。

docker run --name mynginx1 -v C:/zNGINX/testnginx/conf:/etc/nginx/conf.d -p 80:80 -d nginx
Run Code Online (Sandbox Code Playgroud)
  • docker 容器的名称是“mynginx1”
  • v 参数告诉它将计算机上“C:/zNGINX/testnginx/conf”中的任何文件复制到 docker 容器中的“/etc/nginx/conf.d”目录中。这会将您的“default.conf”复制到 docker 容器,NGINX 将读取该配置文件。
  • 注意:确保您的 docker 位置路径中有“conf.d”(“:/etc/nginx/conf.d”),我读过的博客不包含这部分,它只指定了“:/etc/ nginx/",没有它图像就无法启动。
  • p 参数告诉在端口 80 上运行 NGINX

转到以下网址

http://localhost:80/a/b/
Run Code Online (Sandbox Code Playgroud)

NGINX 会将该 URL 重定向到“ http://localhost:3000 ”。因此,您的应用程序现在应该可以从带有基本路径的 URL 访问。单击 s 应该可以工作,链接应该包含指向 NGINX 的基本路径,该路径重定向回应用程序,剥离基本路径,留下任何其他路径。

使用 Docker 的真实世界服务器部署

如果您将应用程序部署到服务器,与本地运行一样,您可以构建应用程序,然后将相关文件/文件夹复制到服务器计算机。确保在构建和运行应用程序时设置了 BASE_PATH

export BASE_PATH=a/b
npm run build

cp package*.json [server_location]
cp next.config.js [server_location]
cp ./next [server_location]
Run Code Online (Sandbox Code Playgroud)

然后在该服务器位置运行

npm install
export BASE_PATH=a/b
npm run start   
Run Code Online (Sandbox Code Playgroud)

注意:如果您在应用程序中引用了“public”中的图像,请使用“next-images”并导入图像,而不是使用 publicRuntimeConfig.basePath 作为前缀。当我做后者时,没有找到图像。有关示例,请参阅关于图像的部分。


may*_*513 5

要添加此处的答案,仅使用basePath是不够的。basePath对于自动指向链接非常有效,但它不会对公共目录中提供的静态文件执行任何操作。

例如,您在or元素public/img/my-img.png中将其称为or ,您必须分别将其更改为or 。imgImage<img src="img/my-img.png" /><Image src="/img/my-img.png" /><img src="your-sub-path/img/my-img.png" /><Image src="/your-sub-path/img/my-img.png" />