!!!!转载请注明作者和本文链接!!!!
为了减少部署时ssl证书申请,降低配置成本想把所有laravel的前端工程配置在一个域名下,结果就卡在二级目录设置这块怎么都出不来结果,也没发现有哪篇文章能详细写一下这种情况下如何配置(可能对于大神来说这种问题是太简单了吧)。现在就把过程中遇到的问题写下来
本地目录配置:
/data/www/www.aaa.com
|___ index.html
|___ /bbb-laravel-web
|___ resources
|___ public
| |___ index.php
| |___ css
| |___ ccc.page.css
|____ ...(其他目录略)
最终想达到的效果是:
浏览器输入www.aaa.com,访问的是/data/www/www.aaa.com/index.html
浏览器输入www.aaa.com/bbb/,访问的是laravel的主页
也就是/data/www/www.aaa.com/bbb-laravel-web/public/index.php
一开始就按着访问后台接口的方式配置的
server {
listen 80;
listen 443;
# ssl 部分省略;
server_name www.aaa.cn;
root /data/www/www.aaa.cn;
access_log /data/log/nginx/www.aaa.cn.access.log main;
error_log /data/log/nginx/www.aaa.cn.error.log debug;
location /{
index index.php index.html;
}
location ^~ /bbb/ {
try_files $uri /bbb-laravel-web/public/index.php;
index index.html index.htm;
index index.html index.php;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
set $script $uri;
set $path_info "/";
if ( $uri ~ "^(.+\.php)(.+)$" ) {
set $script $1;
set $path_info $2;
}
fastcgi_param APP_ENV debug;#这里是使得laravel读取.env.debug下的配置,laravel5.5及以上可以那么搞
fastcgi_param PATH_INFO $path_info;
fastcgi_param SCRIPT_FILENAME $document_root/$script;
fastcgi_param SCRIPT_NAME $script;
}
}
结果出现了
让我们看看都这段发生了什么:
1.首先去查看/data/log/nginx/www.aaa.cn.error.log
2018/08/20 15:25:45 [notice] 2685#2685: *6 "^(.+\.php)(.+)$" does not match "/bbb-laravel-web/public/index.php", client: 123.45.678.90, server: www.aaa.cn, request: "GET /bbb/ HTTP/1.1", host: "www.aaa.cn"
为什么会出现不匹配的情况呢?
1.匹配流程
首先,nginx拿到www.aaa.com/bbb/匹配的是下面这段配置
location ^~ /bbb/ {
try_files $uri /bbb-laravel-web/public/index.php;
index index.html index.htm;
index index.html index.php;
}
我们从开头的本地磁盘root目录(也就是/data/www/www.aaa.cn)下面是没有bbb文件夹,所以$uri是匹配不上的,这个时候就匹配到了“/bbb-laravel-web/public/index.php”。由于它是try_files的最后一项,所以就发生了一个重定向,重定向匹配到了下面这段
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
set $script $uri;
set $path_info "/";
if ( $uri ~ "^(.+\.php)(.+)$" ) {
set $script $1;
set $path_info $2;
}
fastcgi_param APP_ENV debug;#这里是使得laravel读取.env.debug下的配置,laravel5.5及以上可以那么搞
fastcgi_param PATH_INFO $path_info;
fastcgi_param SCRIPT_FILENAME $document_root/$script;
fastcgi_param SCRIPT_NAME $script;
}
}
这段发生了什么呢?我们先来列举下里面的变量
整个url:www.aaa.com/bbb-laravel-web/public/index.php
set $script $uri; # $script=$uri=/bbb-laravel-web/public/index.php
set $path_info "/"; # $path_info="/"
if ( $uri ~ "^(.+\.php)(.+)$" ) {
set $script $1; # $script=(.+\.php)
set $path_info $2; # $path_info=(.+)
}
fastcgi_param PATH_INFO $path_info;
fastcgi_param SCRIPT_FILENAME $document_root/$script;
fastcgi_param SCRIPT_NAME $script;
这段是解析php的,重写了url,访问index.php下路由为变量path_info的页面:
如果匹配不上"^(.+.php)(.+)$",那么就访问路由为/的页面
如果匹配上了,就访问路由(.+)的页面。这个配置逻辑是没有问题的。
由于(.+)表示的是匹配任意字符1~n次,那么/bbb-laravel-web/public/index.php是匹配不上,这时应该访问路由为"/"的页面,那又为什么访问不了呢?
我一开始是怀疑是nginx配置的问题,但是这个404页面是laravel的,说明是可以访问到laravel的,只是laravel内部没有这个路由,但是实际上我是写了"/"路由的。那么laravel内部接收到的是什么路由呢?
本来想着去看一把Laravel内部路由执行的原理,找个地方打log。但是太耗时间了,这个时候用了点小聪明,既然不是“/”的话,那么还有可能的路由便是"/bbb/",于是在app/Provider/RouteServiceProvider.php里面给web路由加了个前缀
protected function mapWebRoutes()
{
Route::prefix('bbb') //这个就是加了的前缀
->middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
然后再测试,居然能访问到“/”路由了,但是页面样式却没了。
问题终于解决了第一步,接下来我们来解决第二步。
首先是看看样式文件为什么没访问到。
这个时候可以在浏览器里右键查看源代码,然后点击样式文件的链接(链接如下)
,结果404了。
<link href="./css/ccc.page.css" rel="stylesheet" type="text/css">
接着就上服务器上看看nginx的error log,log的位置就在上面的配置中
error_log /data/log/nginx/www.aaa.cn.error.log debug;
唔,就是上面这行,中间的是路径,最后的debug表示了log的级别
nginx的debug log设置请看:https://blog.csdn.net/defonds/article/details/11612247
然后看到了这一行
2018/08/21 08:58:50 [error] 11646#11646: *360 open() "/data/www/www.aaa.cn/bbb/css/ccc.page.css" failed (2: No such file or directory), client: 123.45.678.90, server: www.aaa.cn, request: "GET /bbb/css/ccc.page.css HTTP/1.1", host: "www.aaa.cn", referrer: "https://www.aaa.cn/bbb/"
我们看到开始的目录就知道,/data/www/www.aaa.cn是没有bbb文件夹的,那访问bbb/css/ccc.page.css一定是404。要解决这个问题,那就得重写请求了。
location ^~ /bbb {
location ~* ^(.+)\.(gif|jpg|jpeg|png|css|js|ico)$ {
# rewrite语法:rewrite 正则表达式 目标文件 [flag]
# ^表示正则表达式起始,$表示正则表达式结束
# $1,$2,$3表示正则表达式中不同的匹配部分
# $2和$3中间的“\.”表示.号。因为.在正则表达式里是匹配
# 在这里 $1=([a-zA-Z0-9]{3,}),$2=(.+),$3=(gif|jpg|jpeg|png|css|js|ico)
rewrite '^/bbb/([a-zA-Z0-9]{3,})/(.+)\.(gif|jpg|jpeg|png|css|js|ico)$' /bbb-web-laravel/public/$1/$2.$3 last;
}
try_files $uri /bbb-laravel-web/public/index.php;
#root html;
index index.html index.htm;
index index.html index.php;
}
这下好了,不过我寻思着,这个配置能不能再优化下。比如把所有请求都写在public下面,最后的配置如下
location ^~ /meetdate {
alias /data/www/www.aaa.cn/bbb-laravel-web/public;
rewrite '^/meetdate(.*)' /bbb-laravel-web/public$1 last;
}
然后发现SCSS里面的配置url("/image/a.png")路径访问不到,查看源代码发现的路径变成了www.aaa.com/image/a.png,那当然访问不了。然后去看了laravel-sass的文档
文档请见:Compiling Assets (Laravel Mix)
这段话说了两个意思:
1.对于相对路径而言,laravel会在resource(请看最前面的本地路径)下寻找相关的图片文件拷贝到public/images下,然后url重写成了/images/a.png?xxxxxxx
2.对于绝对路径,laravel不会进行url重写
那么像我这种希望不重写,以便最终编译成"../images/a.png"的怎么办呢?
文档也给出了解决办法,就是编译sass的语句后面加上options,代码如下
mix.sass('resources/assets/app/app.scss', 'public/css')
.options({
processCssUrls: false
});
然后就OK了!
撒花么么哒 ✿✿ヽ(°▽°)ノ✿
!!!!转载请注明作者和本文链接!!!!