客户现场需要统一域名,我们管理端的产品使用express+node,因此需要添加合适的二级路径,也就是前缀。
根据网上找到的教程方法,首先将:
app.use(express.static(path.join(__dirname, 'public')));
修改为 :
app.use('/rpsm-web', express.static(path.join(__dirname, 'public')));
在官方API文档里,express.static作为中间件将为指定根目录下的文件提供服务,path.join显然是一个连接方法,将相对根目录与打包后静态资源所属的文件目录(以public为例)连接。
而app.use作为调用中间件的方法,除了常用的匹配路由外,还允许设置虚拟路由。
例如,我们常在app.js里找到:
const index = require('./routes/index.js');
// ...
app.use('/', index);
// 相当于引用了router_index.js的所有路由匹配
// 我理解为vue.js中的routes.push
虚拟路由,相当于给这些路由匹配默认增加 /rpsm-web 的前缀。也就是说,原来请求页面/index同理现在请求页面/rpsm-web/index。
在express.js中,页面路由和接口请求都视作前端服务器的请求,接口匹配默认增加 /rpsm-web 的前缀也同理:
// routes/index.js文件部分内容
// 匹配所有接口请求
// checkParam和checkToken均为中间件的校验方式
router.all('**/*.do', checkParam(), checkToken(), async (req, res) => {
let path = getServiceHosts(req);
return doProxy(req, res, path);
});
至此,所有定义完成。
接下来我只要在公共方法中为封装请求的url添加同一/rpsm-web……
$.ajax({
method: 'POST',
url: globalvar._orgin + '/rpsm-web' + url, // 添加rpsm-web,注意斜杠
dataType: dataType,
contentType: 'application/json',
data: stringifyparms,
async: async,
headers: {
'Service-Name': header,
'param-token': CryptoJS.MD5(stringifyparms).toString()
},
//...
})
当我以为做到这一步就实现了添加/rpsm-web的路由前缀并再次使用外网映射的域名访问时,所有静态资源全部报404。
这时我意识到,我忘记修改静态资源请求路径。
这又涉及到绝对路径和相对路径。
和同事讨论交流后,我最终无法避免使用webstorm的全局替换,将所有相对路径和绝对路径中包含/css/、/js/、/utils/、/images/一一替换。
其实这一需求从理解上讲非常简单:打开F12,让所有请求以rpsm-web为前缀。
调研过程中,我有思考过:
1)express是否支持为全局请求设置中间件?—— 答:否。
2)是否允许在触发请求时重定向到新的路由?——答:在触发302之前,仍会导致404。