问题描述:浏览器加载页面时,读取不到服务器js静态资源,造成页面内容加载失败。
首先讲下排查思路。
首先浏览器处理静态资源一定是从资源服务器加载,经过代理层,返回给浏览器,浏览器进行解析,并递归去加载页面中的其他的静态资源文件,直到需要加载的资源加载完毕。
其次分析为什么加载不上,三种可能:
1、服务器不具备该资源
2、服务器具备资源但客户端访问地址错误
3、服务器具备资源,访问地址正确,但代理没有代理静态资源文件
按着这种思路排查。
1、 登录服务器,发现服务器端静态资源存在[排除]
2、查看代理层nginx配置文件,对该静态资源有代理映射[排除]
3、查看nginx日志,看到访问日志正常,客户端请求正常经过代理。[排除]
既然都正常,为什么会出现访问不到,根据错误信息,明显是没有该对象定义。
回顾自己的问题排查思路,在源码中,找到interfaceConfig定义。
最后在index.html找到interface_config.js的静态引用
没有接触过这种引用,所以专门查了一下,解释如下:
一般网站和网站平台的制作始于静态页面,如果页面数量非常巨大,就会出现很多重复的代码(头部,底部,侧边栏,导航......),在和后台对接的时候很不友好,基于前端页面模块化的思想,我们可以将那些重复的代码单独提出来放在一个文件内,当某些页面需要这些模块时,采用<!--#include virtual="xxx.xxx" -->的方式将那一块的html代码导入到这里,避免出现代码冗余。
到这里似乎还是没有任何的眉目,了解下正常的js加载的流程。
本地加载:<script type='text/javascript' src='test.js'></script>
远端加载:<script type='text/javascript' src='www.tonyweb.com/test.js'></script>
这里只考虑浏览器代理的远端加载,到这里可以看出来,很有可能对于这种格式 <!--#include virtual="xxx.xxx" -->
的文件nginx没有代理。
既然没有思路验证完毕,那么考虑下, 为什么会没有?肯定是代理没有将文件代理过来,绕了一圈又回到Nginx,查看access.log,发现浏览器并没有对interface_config.js代理,结合远端加载,因为不是代理地址,加载必定是本地浏览器缓存,那么可能是nginx在代理时,处理过这种标签,根据这种思路,去nginx官方文档翻了下,发现SSI模块的解释:
SSI Commands
Once you have the SSI engine enabled for your web pages, you are ready to start writing your first dynamic HTML page. Again, the principle is simple — design the pages of your website using regular HTML code, inside which you will insert SSI commands.
These commands respect a particular syntax — at first sight, they look like regular HTML comments: <!-- A comment -->, and that is the good thing about it — if you accidentally disable SSI parsing of your files, the SSI commands do not appear on the
client browser; they are only visible in the source code as actual HTML comments. The full syntax is as follows:<!--# command param1="value1" param2="value2" … -->
The main command of the Server Side Include module is obviously the include command. It comes in two different fashions.
First, you are allowed to make a simple file include:
<!--# include file="header.html" -->
This command generates an HTTP sub-request to be processed by Nginx. The body of the response that was generated is inserted instead of the command itself.
The second possibility is to use the include virtual command:
<!--# include virtual="/sources/header.php?id=123" -->
看到官方的解释有些欣慰, 因为和思路匹配。
上面大概意思是说,SSI模块支持<!--# include virtual="/sources/header.php?id=123" -->这种格式的服务器解析,也就说加载html的时候,nginx代理层会根据SSI command #include将资源文件包含进来。
至此,问题似乎有了眉目,去查看下是否开启SSI,发现配置文件中的确没有配置,下面就是验证问题。
验证之前,先了解下SSI:
SSI:Server Side Include,是一种基于服务端的网页制作技术,大多数(尤其是基于Unix平台)的web服务器如Netscape Enterprise Server等均支持SSI命令。
它的工作原因是:在页面内容发送到客户端之前,使用SSI指令将文本、图片或代码信息包含到网页中。对于在多个文件中重复出现内容,使用SSI是一种简便的方法,将内容存入一个包含文件中即可,不必将其输入所有文件。通过一个非常简单的语句即可调用包含文件,此语句指示 Web 服务器将内容插入适当网页。而且,使用包含文件时,对内容的所有更改只需在一个地方就能完成。
在nginx中添加ssi配置如下:
ssi on;
ssi_silent_errors on;
ssi_types text/shtml;
重新访问,访问成功,查看服务器nginx access.log,成功代理静态文件。