问题描述
我正在开发我的第一个NextJS应用程序.当我运行"npm run dev"或"npm run start"时,它将我的应用程序部署到
http://host:port/
当我导航到页面时,URL变为
http://host:port/page1
我需要拥有自己的特定URL,例如
http://host:port/my-test-application/path-for-my-app/
http://host:port/my-test-application/path-for-my-app/page1
此外,我的应用程序具有很多链接到应用程序其他区域的元素,我需要这些元素还可以通过basePath转到URL,而不仅仅是转到根路径.
我还将把该应用程序分配给具有不同basePath的其他服务器,因此无法在我的应用程序中对其进行硬编码.
我该怎么做?
使用其他应用程序(例如react/vue/angular/native JS),我仅构建应用程序并将构建代码放在服务器上的"my-test-application/path-for-my-app"文件夹中. /p>
我在NextJS应用程序中尝试了此操作,但遇到一个错误,即找不到".next"文件夹.
我用Google搜索,可以找到一些有关使用"assetPrefix"或"Zones"的参考.但是我真的不明白我该怎么办.
我如何将我的应用程序部署到特定的URL
解决方案1:重组页面"-不允许我将其部署到具有不同basePath的其他服务器上
我可以在页面"目录中创建文件夹结构,并更改所有元素以使用此文件夹结构.
|- pages
|- my-test-application
|- path-for-my-app
|- index.js
|- page1.js
<Link href="/my-test-application/path-for-my-app/page1" >
我不喜欢这种解决方案,因为basePath已硬编码到我的应用程序中,以适应部署设置.
如果我想将我的应用程序部署在2个具有不同basePath的服务器上(即下面),则必须具有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
已更新:我已于3月5日更新了此问题,其中包括我需要s正常工作以及不喜欢的一种解决方案.
我找到了使用NGINX反向代理具有基本路径的URL的解决方案.
有用的链接
- https://levelup.gitconnected.com/deploy-your-nextjs-application-on-a-different-base-path-ie-not-root-1c4d210cce8a
- https://www. docker.com/blog/tips-for-deploying-nginx-official-image-with-docker/
应用程序更改
依赖项
- next-images:为了在使用反向代理时从"public"导入静态图像
- @ zeit/next-css:为了使用样式表文件
- 以及通常的NextJS依赖项
next.config.js
在应用程序的根目录中添加一个"next.config.js"文件,以便您可以指定"assetPrefix"和"publicRuntimeConfig.basePath"
- assetPrefix:在访问组件,样式表,页面等时,由NextJS使用
- publicRuntimeConfig.basePath:在s中使用,因此指定要添加到链接的前缀,在使用公共图像时在"元素的"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() ,
},
}));
静态图片
使用下一张图片"导入图片并在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>
);
}
}
注意:我尝试使用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>
链接
更改您的链接以使用基本路径前缀,例如在我的标题"组件中,我具有以下内容
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;
注意:在博客 https://levelup.gitconnected.com/deploy-your-nextjs-application-on-a-different-base-path-ie-not-root-1c4d210cce8a ,包含一个为您添加前缀的"Link.tsx",因此您只需使用该Link组件(从"./Link.tsx"导入Link;),而不是nextJS版本(从'next/link导入Link) ';).但是,当我在链接URL中有变量时,"Link.tsx"对我不起作用.
运行您的nextjs应用
在不希望使用基本路径的情况下在本地运行应用程序时,只需运行
npm run dev
由于未指定BASE_PATH,因此应可从" http://localhost:3000 和您的src访问应用程序值应为"/image_name1.png",将鼠标悬停在s上时,您将看到链接为" http://localhost :3000/pagename "
要使用基本路径运行时,请执行以下操作
export BASE_PATH=a/b
npm run dev
注意:由于某种原因,在我的环境中,如果我指定"export BASE_PATH =/a/b"(/在路径的开头),则会在该路径的开头添加一个文件夹目录.因此,我在没有开始/的情况下指定了它,并且next.config.js中的代码在需要时添加了开始/.
您无法通过" http://localhost:3000 访问您的应用,因为您具有基本路径/assetPrefix/publicRuntimeConfig.basePath设置.现在您需要反向代理.
NGINX:反向代理
我发现最简单的设置是使用NGINX docker映像.您需要使用包含重定向到NextJS应用程序的配置来运行NGINX.
创建一个文件夹,然后在该文件夹中添加一个"default.conf"文件.确保在启动nextjs应用程序时放置在位置"中的路径是您为BASE_PATH指定的SAME路径.
server {
listen 80;
server_name localhost;
location /a/b/ {
proxy_pass http://myhost:3000/;
}
}
重要说明:
- 您必须在proxy_pass URL的末尾加上/,否则其他路径不会传递到NextJS应用程序中
- 如果在该位置使用变量,则必须确保包括传递路径
示例
location ~ /a/b/(.*)$ {
set $upstream http://myhost:3000/$1;
proxy_pass $upstream;
}
在该目录的命令提示符下,运行NGINX docker映像,告诉它使用您的配置文件.
docker run --name mynginx1 -v C:/zNGINX/testnginx/conf:/etc/nginx/conf.d -p 80:80 -d nginx
- 泊坞窗容器的名称为"mynginx1"
- v参数告诉它将计算机上"C:/zNGINX/testnginx/conf"中的所有文件复制到docker容器中的"/etc/nginx/conf.d"目录中.这会将您的"default.conf"复制到docker容器中,NGINX将读取该配置文件.
- 注意:请确保您在docker位置(:/etc/nginx/conf.d")的路径中具有"conf.d",我阅读的博客不包括此部分,它仅指定了:". /etc/nginx/",如果没有该图片,则无法启动.
- p参数告诉在端口80上运行NGINX
转到以下网址
http://localhost:80/a/b/
NGINX会将URL重定向到" http://localhost:3000 ".因此,现在应该可以从具有基本路径的URL访问您的应用程序.单击s应该可以工作,链接中应包含指向NGINX的基本路径,该路径将重定向回应用程序,并剥离该基本路径,并保留所有其他路径.
使用Docker的Real World Server部署
如果要将应用程序部署到服务器(如本地运行一样),则可以构建应用程序,然后将相关文件/文件夹复制到服务器计算机上.在构建和运行应用程序时,请确保已设置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]
然后在该服务器上运行
npm install
export BASE_PATH=a/b
npm run start
注意:如果您在应用程序中引用了公共"中的图像,请使用下一个图像"并导入图像,而不要使用publicRuntimeConfig.basePath作为前缀.当我做后者时,没有找到图像.有关示例,请参见关于图像的部分.
I am working on my first NextJS application. When I run "npm run dev" or "npm run start" it deploys my application to
http://host:port/
When I navigate to a page the url becomes
http://host:port/page1
I need to have my own specific URL, such as
http://host:port/my-test-application/path-for-my-app/
http://host:port/my-test-application/path-for-my-app/page1
Furthermore, my app has a lot of elements to link to other areas of the applications, i need these to also go to URL with the basePath and not just go to the root path.
I will also be depolying this app to different servers which will have different basePaths, therefore this can not be hardcoded in my app.
How can I do this?
With other applications such as react/vue/angular/native JS, I simply build my application and put the build code in a "my-test-application/path-for-my-app" folder on my server.
I tried this with my NextJS application but i got an error that ".next" folder could not be found.
I googled and could find some references to using "assetPrefix" or using "Zones". However I do not really understand what I am supposed to do.
How do i get my app deployed to specific URL
Solution 1: Restructure "pages" - Does not enable me to deploy to different servers with different basePaths
I could create the folder structure inside my "pages" directory and change all my elements to use this folder structure.
|- pages
|- my-test-application
|- path-for-my-app
|- index.js
|- page1.js
<Link href="/my-test-application/path-for-my-app/page1" >
I dislike this solution as the basePath is hardcoded into my application, as to apposed to a deployment setting.
If I wanted to deploy my app on 2 servers with different basePaths (i.e. below) I would have to have 2 versions of the code.
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
Updated: I have updated this question on 5th March to include my need for s to work and one solution which I do not like.
I found a solution using NGINX to reverse proxy a URL with the base path.
Useful links
- https://levelup.gitconnected.com/deploy-your-nextjs-application-on-a-different-base-path-i-e-not-root-1c4d210cce8a
- https://www.docker.com/blog/tips-for-deploying-nginx-official-image-with-docker/
Application Changes
Dependencies
- next-images : in order to import static images from "public" when using a reverse proxy
- @zeit/next-css : in order to use stylesheet files
- as well as usual NextJS dependencies
next.config.js
Add a "next.config.js" file at the root of your application so that you can specify the "assetPrefix" and "publicRuntimeConfig.basePath"
- assetPrefix : used by NextJS when accessing components, stylesheets, pages etc
- publicRuntimeConfig.basePath : used in s so specify the prefix to add to the link, used in "src" tags of "" elements when using public images
Example
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() ,
},
}));
Static images
Use "next-images" in order to import the images and reference the imported object in the 's src tags
Change any references to your static images (those in /public folder) to have the base path prefix. For example my "Footer" component has the following
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>
);
}
}
Note: I tried to use the publicRuntimeConfig.basePath as a prefix to the src URL (as below), but this did not work in my deployed environment (see below)
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>
Links
Change your Link's to use the base path prefix, for example in my "Header" component i have the following
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;
Note: In the blog https://levelup.gitconnected.com/deploy-your-nextjs-application-on-a-different-base-path-i-e-not-root-1c4d210cce8a, it contains a "Link.tsx" that does the adding of the prefix for you, so you simply use that Link component (import Link from "./Link.tsx";) and not the nextJS version (import Link from 'next/link';). However, that "Link.tsx" does not work for me when I have variables in my link URLs.
Running your nextjs app
When running your application locally when you do NOT want a base path you can just running
npm run dev
As no BASE_PATH is specified your application should be accessible from "http://localhost:3000" and your src values should be "/image_name1.png" and when you hover over your s you will see the link is "http://localhost:3000/pagename"
When you want to run with a base path do the following
export BASE_PATH=a/b
npm run dev
Note: for some reason in my environment if i specify "export BASE_PATH=/a/b" (/ at the start of the path) I get a folder directory added to the beginning of the path. Therefore i specify it without the starting / and the code in next.config.js adds the starting / if need be.
You can not access your app at "http://localhost:3000" as you have the base path/assetPrefix/publicRuntimeConfig.basePath set. Now you need a reverse proxy.
NGINX : Reverse Proxy
I found the easiest setup was to use a NGINX docker image. You need to run NGINX with a configuration containing the redirection to your NextJS app.
Create a folder and add in that folder a "default.conf" file. Make sure the path you put in your "location" is the SAME path you specified for BASE_PATH when starting your nextjs app.
server {
listen 80;
server_name localhost;
location /a/b/ {
proxy_pass http://myhost:3000/;
}
}
Important Notes:
- you have to have the trailing / on the end of your proxy_pass URL otherwise additional paths are not passed onto your NextJS apoplication
- if you use a variable in the location you must make sure you include passing on the paths
example
location ~ /a/b/(.*)$ {
set $upstream http://myhost:3000/$1;
proxy_pass $upstream;
}
In a command prompt from that directory run a NGINX docker image, telling it to use your config file.
docker run --name mynginx1 -v C:/zNGINX/testnginx/conf:/etc/nginx/conf.d -p 80:80 -d nginx
- name of the docker container is "mynginx1"
- the v parameter is telling it to copy any files in "C:/zNGINX/testnginx/conf" on your computer to the "/etc/nginx/conf.d" directory in the docker container. This will copy your "default.conf" to the docker container and NGINX will read that configuration file.
- Note: Make sure you have the "conf.d" in your path for the docker location (":/etc/nginx/conf.d"), blogs I read did not include this part, it only specified ":/etc/nginx/", and without it the image doesn't start.
- the p parameter is telling to run NGINX on port 80
Go to the following URL
http://localhost:80/a/b/
NGINX will redirect that URL to "http://localhost:3000". Therefore your application should now be accessible from the URL with the base path. Clicking on s should work, the link should contain the base path which goes to NGINX which redirects back to the application stripping off the base path leaving any other paths.
Real World Server Deployment using Docker
If you are deploying your application to a server, as apposed to running locally, you can build your application and then copy the relevant files/folders to the server machine. Make sure you have the BASE_PATH set when both building and running your app
export BASE_PATH=a/b
npm run build
cp package*.json [server_location]
cp next.config.js [server_location]
cp ./next [server_location]
then on that server location run
npm install
export BASE_PATH=a/b
npm run start
Note: If you have images in "public" that you reference in your app, use "next-images" and import the image rather than use the publicRuntimeConfig.basePath as a prefix. When i did the latter the images were not found. See the section about about images for examples.
这篇关于NextJS部署到特定的URL路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!