最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    正文概述 掘金(红尘炼心)   2021-01-21   1708

    前言

    一个产品在A工程中开发,开发完后将A工程部署在域名XXX( www.xxx.com )根路径上,那么在域名XXX后面加上A工程中路由配置的路径,就可以访问A工程中对应的页面。

    这个产品在后期的迭代中,有几个新功能不在A工程中开发了,要新起一个B工程来开发。通常一个产品只会对外提供一个域名,于是B工程也要部署在域名XXX上。那么问题来了,在域名XXX后面添加路径只会访问到A工程中的页面,访问不到B工程中的页面。

    为了解决这个问题,就要用把B工程部署到域名XXX的子路径上。比如部署到 www.xxx.com/bbb/ 上,然后在 www.xxx.com/bbb/ 后面加上B工程中路由配置的路径,就可以访问B工程中对应的页面。

    本专栏用Nginx部署Vue工程作为例子。

    一、安装Nginx

    打开 Nginx 官网下载地址,点击 nginx / Windows-1.18.0 下载稳定版的 Nginx 。下载完成后,随便找个地方安装,安装完成后打开软件安装目录。Nginx 的主要配置文件都在 conf 文件夹中。

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    二、常用的Nginx命令

    在Nginx软件安装目录的地址栏中输入cmd,打开命令行工具。

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    以下有一些常用的命令,需要熟悉一下。

    • 启动Nginx start nginx
    • 停止Nginx nginx.exe -s quit
    • 重启Nginx nginx.exe -s reload
    • 检查Nginx配置是否正确 nginx -t

    三、跟部署相关的Nginx配置语法

    3.1、server块的配置语法

    server的作用是在服务器上创建一个虚拟主机。

    可以简单地把虚拟主机理解成一个虚拟服务器。Nginx默认在 conf/nginx.conf 文件中配置了一个server块,如下所示:

    http{
      server{
        listen 80;
        server_name  localhost;
      }
    }
    

    启动Nginx,用浏览器中访问 http://localhost:80 ,访问页面如下所示:

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    在Nginx中每配置一个server块,当启动Nginx时,就会在服务器上创建一个虚拟服务器并启动它。http块中可以包含多个server块,那么在http块中再配置一个server块,配置内容如下所示:

    http{
      server{
        listen 8081;
        server_name  test.com;
      }
    }
    

    重启Nginx,用浏览器访问 test.com:8081 ,会发现无法访问。这因为在Host文件中还没把 test.com 指向 127.0.0.1 。

    这里推荐一个修改 Host 的工具(Switchhosts!),可以自行百度搜索下载安装,修改好Host文件后,重新用浏览器访问 test.com:8081 ,访问结果会和访问 http://localhost:80 的页面一样。

    其中 listen 的作用就是监听服务的某个端口。server_name 的作用是给服务起个名称(域名)。

    3.2、include指令在http块中的应用

    Vue工程编译打包生成的文件需要部署在服务器上才能运行起来。为了更好管理每个Vue工程对应的服务部署配置,在 conf 文件夹中创建一个 vhost 文件夹,在 vhost 文件夹中根据每个Vue工程创建对应的部署配置文件,如下图所示:

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    其中 a.conf 文件代表A工程对应的部署配置文件。

    再利用 include 指令把 conf/vhost 文件夹中每个文件中的server块添加到conf/nginx.conf 文件中的http块中。

    于是在 conf/nginx.conf 文件中的http块中添加如下配置:

    http{
      //...
      include vhost/*.conf;
      server_names_hash_bucket_size 64;
    }
    

    其中 vhost/*.conf 表示 vhost 文件下的所有以 .conf 结尾的文件。server_names_hash_bucket_sizeserver_name 的存储大小。

    3.3、location块的配置语法

    location块的作用是匹配用户访问服务所用的url的路径部分,匹配成功即进行相关的操作。其语法是location [=|~|~*|^~|@] pattern { ... },其中[=|~|~*|^~|@]是修饰符,pattern是匹配规则,在{ ... }中配置相关的操作。

    其中修饰符是非必须的,若没修饰符,仍然可以用pattern(匹配规则)去匹配url的路径部分。修饰符的种类及作用如下表所示:

    修饰符作用
    =对应的匹配规则是个字符串,表示对url的路径进行精确匹配,即该字符串等于url的路径部分。~对应的匹配规则是个正则,表示匹配时区分大小写。~*对应的匹配规则是个正则,表示匹配时区分大小写。^~对应的匹配规则是个字符串,表示匹配时要检测url的路径中是否含有该字符串。@用于定义一个location块,且该块不能被外部访问,只能被Nginx内部指令所访问。

    此外修饰符还有另外一个作用,提高location块匹配的优先级,其优先级如下所示:

    `[=]` > `[^~]` > `[~/~*]` > 无修饰符
    

    location块匹配的大致流程:

    • 第一步:优先使用 = 修饰符的location块的匹配规则去匹配,= 意味精确匹配,如果匹配上了,该location中的操作马上执行,匹配过程就此结束;

    • 第二步:若没匹配上,接下来去匹配那些匹配规则是字符串的location块,若被多个location块匹配上,取其中匹配规则最长的location块,若该location块的匹配规则前面有 ^~ 修饰符,马上执行其中操作,匹配过程结束。若该location块的匹配规则前面没有修饰符,先记录该location块继续往下匹配。

    • 第三步:若匹配规则是字符串的location块没有匹配上,或者匹配上的location块的修饰符不是 ^~。那么接下来去匹配那些匹配规则是正则的location块。这里要注意如果匹配规则是正则,那么其前面一定要加上 ~~* 修饰符,否则不起作用。 若被多个location块匹配上,则按着location块的定义顺序,取顺序最上面的location块进行匹配,马上执行其中操作,匹配过程结束。

    • 第四步:若匹配规则是正则的location块没匹配上,要去看一下第二步中,若有无修饰符的location块匹配上,马上执行其中操作,匹配过程结束。若没有,匹配过程也照样结束。

    关于第二步中,取其中匹配规则最长的location块举个例子说明:

    server{
      listen 8081;
      server_name  test.com;
      location ^~ /doc {
        return 001;
      }
      location ^~ /docu {
        return 002;
      }
    }
    

    执行命令 curl -I test.com:8080/document 发起一个网络请求,结果是返回 002 ,如下图所示:

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    其中 ^~ /doc^~ /docu 都能匹配 url 路径 /document 。因为 /docu 字符串的长度比 /doc 长,所以匹配规则为 ^~ /docu 的location块被匹配上。

    3.4、root指令和alias指令在location块中的区别

    在匹配规则为字符串的location块中,用 root 指令和 alias 指令是用来指定通过url访问服务器(指用server块创建的虚拟服务器,为了行文方便将其简称为服务器)的根目录路径的结果是不一致的。下面用一个例子来说明:

    nginx.conf 中 http 块中添加如下配置

    server{
      listen 8081;
      server_name  test.com;
      location ^~ /doc {
        root   html;
      }
    }
    

    其中html是指Nginx安装目录中的html文件夹的路径。

    用浏览器访问 test.com:8080/doc ,页面上会显示 404 错误。这是因为通过 root 指定服务器的根目录路径,会把location块的匹配规则 /doc 给拼接上,此时服务器的根目录路径为 html/doc,而 html 文件夹中根本没有 doc 文件夹,故会显示 404 错误。

    现在把上述配置中的 root html; 替换成 alias html; 后,重启Nginx,用浏览器访问 test.com:8080/doc ,此时访问页面显示出正常页面。这是因为通过 alias 指定服务器的的根目录路径,不会去拼接location块的匹配规则,alias 后面配置的路径就是服务器的根目录路径。

    3.5、index指令在location块的应用

    index 指令的作用是指定当访问服务器的url路径后面没指定访问文件时默认访问的文件。默认是index.html。

    index指令可以配置多个文件,用空格隔开。文件可以用文件的相对路径或绝对路径来配置,若是绝对路径要放在最后配置。 如果配置多个文件,Nginx会根据文件的配置顺序从前往后来查找,直到查找到真实存在的文件。要注意文件的相对路径是相对于所在 location块中配置的服务器根目录路径。

    下面用一个例子来说明:

    一般的Vue工程编译打包后都是以index.html,但是在多入口的Vue工程编译打包后会出现多个 .html 文件。比如一个多入口的Vue工程编译打包后的文件目录如下图所示:

    『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    其中 a.htmlb.html 文件都为工程的入口文件。把 dist 文件夹放入Nginx安装的根目录中。用Nginx来部署这个工程,那么应该如此配置:

    server{
      listen 8081;
      server_name  test.com;
      location / {
        root   dist;
        index a/a.html;
      }
      location ^~ /b {
        root   dist;
        index b.html;
      }
    }
    

    3.6、try_files指令在location块的应用

    try_files 指令的作用是尝试查找文件。其语法是try_files file ... uri;, 其中 file 是文件的相对路径,可以配置多个,uri 是url路径。要注意文件的相对路径是相对于所在location块中配置的服务器根目录路径。 Nginx会根据文件路径配置的顺序从前往后来查找,并使用第一个找到的文件的配置路径进行请求处理,如果通过配置的文件路径都没有找到对应的文件,则把最后一个配置的 uri 去匹配对应的location块。

    在项目中使用history模式的路由,为了避免通过url访问到的页面不存在时,返回浏览器自带的404页面。要在location块中增加一行配置,配置如下所示:

    location / {
      try_files $uri $uri/ /index.html;
    }
    

    其中 $uri 是 url 的路径及文件名,例如访问 http://test.com:8080/doc$uri 就是 /doc

    $uri/ 会去访问路径下的默认访问文件。例如 doc 文件夹下有 index.html 文件,访问 http://test.com:8080/doc 时,可以通过 $uri/ 访问 doc/index.html 文件 。

    假设一个工程编译打包后只有一个入口文件 index.html, 那么 try_files $uri $uri/ /index.html; 的作用就是用任何 url 访问工程中的页面,最终都会访问到入口文件 index.html,这样当访问工程中的页面不存在时,会访问工程中的404页面,而不会访问浏览器自带的404页面。

    3.7、proxy_pass指令在location块的应用

    代理有正向代理和反向代理两种,都是用proxy_pass指令来实现。

    一句话解释正向代理,正向代理的对象是用户,用户知道访问那个服务器,而服务器不知道是那个用户访问它。

    举个例子来解释正向代理,假如你要访问一个网站,但是你没有权限访问这个网站。此时小明有权限访问这个网站,那么你可以让小明帮忙访问这个网站,把访问结果告诉你。在此过程中,小明就是你的代理,你就是客户端,网站就是服务端,网站只知道小明访问了它而不知道你访问了它。

    一句话解释反向代理,反向代理的对象是服务器,用户不知道访问了那个服务器,而服务器知道那个用户访问它。

    举个例子来解释方向代理,一个网站有很多人访问,一个服务器承载不住这么多人的访问,那么就把网站部署到很多台服务器上,这时用一个服务器做代理,假设用户 A,B,C都访问了这个网站,会访问代理服务器,代理服务器通过计算把用户 A,B,C分别导流到不同的服务器上。在此过程中,用户只知道访问了代理服务器,而不知道真正访问的服务器,但真正的服务器可以知道是那个用户访问了它。

    在部署项目中,一般用到反向代理。可以用 proxy_pass 指令实现最简单的反向代理。

    例如访问 test.com:8080/doc ,用反向代理访问到 http://127.0.0.1:8001/ 这个服务,其配置如下所示:

    server{
      listen 8080;
      server_name  test.com;
      location ^~ /doc {
        proxy_pass: http://127.0.0.1:8001/
      }
    }
    

    3.8、rewrite指令在location块的应用

    rewrite 的作用是重定向。其语法是 rewrite regex replacement [flag];

    • regex 是匹配url路径的正则表达式;

    • replacement 是重定向的地址,要注意在location块中使用且值为文件路径时,如果location块中未定义服务器根目录路径,则是将Nginx安装目录中 html 文件夹的路径作为参照路径,如果有定义服务器根目录路径,就以服务器根目录路径为参照路径;

    • flag 是标志位,在location块中一般使用 break,表示执行完rewrite,不会继续匹配其它location块。如果使用 last,表示执行完rewrite,会继续匹配其它location块。

    四、部署方案

    把Vue工程部署到域名的子路径上有三种方案:

    • 利用反向代理来部署;

    • 利用root配置来部署;

    • 利用alias配置来部署。

    不管那种部署方案都需要用location块来匹配对应的访问url路径并做处理。下面分别介绍一下三种部署方案的Nginx配置,至于配置过程中所用到的Nginx语法已在上面介绍了。

    4.1、准备工作

    • 假设要部署在域名的子路径 /bbb/ 上,要先更改Vue工程中的配置,且用 Vue CLI3 和 Vue CLI2 搭建的Vue工程,更改的地方不一样。

      • 用Vue CLI3搭建:
        • vue.config.js 文件中修改publicPath为/bbb/;
          module.exports = {
             publicPath: process.env.NODE_ENV == 'development' ? '/' : '/bbb/',
          }
          
        • 修改路由的基路径 base;
          const router = new Router({
            //...
            base: process.env.BASE_URL,
          });
          
      • 用Vue CLI2搭建:
        • config/index.js中修改如下配置:
          module.exports = {
            build: {
              assetsPublicPath: '/bbb/',
            }
          }
          
        • 修改路由的基路径 base
          const router = new Router({
            //...
            base: /bbb/,
          });
          
    • 在服务器上找个地方,安装一下Nginx,在Nginx安装目录中找到 conf 文件夹,在其中创建一个 vhost 文件夹,专门来管理每个工程的部署配置;

    • 在服务器上找个地方,用 git 把要部署的工程代码克隆下来,找到工程编译打包后生成的文件所在位置,记下其路径。

    4.2、利用反向代理来部署

    conf/vhost 文件夹下创建 A.conf 来写入A工程部署到域名XXX( www.xxx.com )根路径上的部署配置,如下所示:

    # A.conf
    server {
      listen 80;
      server_name xxx.com;
      location / {
        root /home/ec2-user/git_src/avue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
    }
    

    其中 root 所配置是 A 工程编译打包后生成文件的路径。

    conf/vhost 文件夹下创建 B.conf 来写入B工程部署到端口为8081的服务上的部署配置,如下所示:

    server {
      listen 8001;
      location / {
        root /home/ec2-user/git_src/bvue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
    }
    

    conf/vhost/A.conf 文件中添加反向代理的配置,实现访问 www.xxx.com/bbb/ 时,通过反向代理访问 http://10.203.19.74:8081/ ,其中 10.203.19.74 为真实服务器ip地址。这样间接实现了在域名XXX( www.xxx.com )的子路径 /bbb/ 上部署了B工程。反向代理配置如下所示:

    # A.conf
    server {
      listen 80;
      server_name xxx.com;
      location / {
         root /home/ec2-user/git_src/avue/dist;
         try_files $uri $uri/ /index.html;
         index index.html;
      }
      location ^~ /bbb {
        proxy_pass http://10.203.19.74:8081/;
      }
    }
    

    4.3、利用alias配置来部署

    conf/vhost/A.conf 文件中写入所示的配置:

    # A.conf
    server {
      listen 80;
      server_name xxx.com;
      location / {
        root /home/ec2-user/git_src/avue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
      location ^~ /bbb {
        alias /home/ec2-user/git_src/bvue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
    }
    

    此外还要处理一下访问工程中的页面不存在时的场景,例如用 www.xxx.com/bbb/test 访问工程,其中 /test 路径在工程的路由中未定义。按原先的配置,会访问到A工程中的404页面。

    这是因为匹配规则为 /bbb 的location块中 try_files 指令的最后一个参数引起的。按着前面对 try_files 指令的介绍,在 try_files 指令执行中没有找到匹配的文件后,会用 /index.html 去匹配其它location块。于是匹配到匹配规则为 / 的location 块,导致访问B工程中未定义的页面会访问到A工程中404页面。

    这里用修饰符 @ 创建一个内部的location块(@router),在这个location块中用 rewrite 指令来解决这个问题。配置如下所示:

    # A.conf
    server {
      listen 80;
      server_name xxx.com;
      location / {
        root /home/ec2-user/git_src/avue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
      location ^~ /bbb {
        alias /home/ec2-user/git_src/bvue/dist;
        try_files $uri $uri/ @router;
        index index.html;
      }
      location @router {
        root /home/ec2-user/git_src/bvue/dist;
        rewrite ^.*$ /index.html break;
      }
    }
    

    要注意在location块中使用 rewrite 指令,要定义服务器根目录路径,不然重定向的相对路径会相对于Nginx的安装目录中的html文件夹路径。且定义内部location块时只能用root指定服务器跟目录路径。此外 rewrite 指令的标志位也要选择 break,不然执行完rewrite还会继续匹配其它location块,最终还是会匹配到规则为 / 的location块,导致访问B工程中未定义的页面会访问到A工程中404页面。

    4.4、利用root配置来部署

    conf/vhost/A.conf 文件中写入如下所示的配置:

    # A.conf
    server {
      listen 80;
      server_name xxx.com;
      location / {
        root /home/ec2-user/git_src/avue/dist;
        try_files $uri $uri/ /index.html;
        index index.html;
      }
      location ^~ /bbb {
        root /home/ec2-user/git_src/bvue/;
        try_files $uri $uri/ @router;
        index index.html;
      }
      location @router {
      	root /home/ec2-user/git_src/bvue/dist;
      	rewrite ^.*$ /index.html break;
      }
    }
    

    同时要把工程编译打包生成的文件夹名称改成和所部署域名的子路径一样。在Vue工程中可以这么配置。

    • 用Vue CLI3搭建:在 vue.config.js 文件中修改outputDir为bbb;
      module.exports = {
        outputDir: 'bbb',
      }
      
    • 用Vue CLI2搭建:在 config/index.js 文件中修改如下配置:
      module.exports = {
        build: {
          //...
          assetsRoot: path.resolve(__dirname, '../bbb'),
        }
      }
      

    起源地下载网 » 『前端工程』—— 用Nginx把前端工程部署到域名的子路径上

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元