大多数Web应用程序都需要URL解析,无论是提取域名,实现REST API还是查找图像路径。 下图描述了典型的URL结构:
您可以使用正则表达式将URL字符串分解为组成部分,但这是复杂且不必要的……
服务器端URL解析
Node.js(以及io.js之类的fork)提供了URL API :
// Server-side JavaScript
var urlapi = require('url'),
url = urlapi.parse('http://site.com:81/path/page?a=1&b=2#hash');
console.log(
url.href + '\n' + // the full URL
url.protocol + '\n' + // http:
url.hostname + '\n' + // site.com
url.port + '\n' + // 81
url.pathname + '\n' + // /path/page
url.search + '\n' + // ?a=1&b=2
url.hash // #hash
);
如您在上面的代码段中所见, parse()
方法返回一个对象,该对象包含所需的数据,例如协议,主机名,端口等。
客户端URL解析
浏览器中没有等效的API。 但是,如果浏览器做得很好,那就是URL解析,并且DOM中的所有链接都实现类似的Location接口,例如:
// Client-side JavaScript
// find the first link in the DOM
var url = document.getElementsByTagName('a')[0];
console.log(
url.href + '\n' + // the full URL
url.protocol + '\n' + // http:
url.hostname + '\n' + // site.com
url.port + '\n' + // 81
url.pathname + '\n' + // /path/page
url.search + '\n' + // ?a=1&b=2
url.hash // #hash
);
如果我们有一个URL字符串,我们可以在内存中的锚元素( a
)上使用它,这样就可以在不使用正则表达式的情况下对其进行解析,例如:
// Client-side JavaScript
// create dummy link
var url = document.createElement('a');
url.href = 'http://site.com:81/path/page?a=1&b=2#hash';
console.log(url.hostname); // site.com
同构网址解析
Aurelio最近讨论了同构JavaScript应用程序 。 从本质上讲,它是一种渐进的增强,将其扩展到了一个极端的水平,在该水平上,应用程序可以在客户端或服务器上愉快地运行。 使用现代浏览器的用户将使用单页应用程序。 较旧的浏览器和搜索引擎机器人会看到服务器渲染的替代方案。 从理论上讲,应用程序可以根据设备的速度和带宽能力实现不同级别的客户端/服务器处理。
同构JavaScript已经讨论了很多年,但是它很复杂。 没有什么项目比这更进一步了
实现可共享的视图,并且在很多情况下,标准的渐进式增强不能很好地起作用(如果没有客户端JavaScript的话,大多数“同构”框架似乎会失败) 。 也就是说,可以创建与环境无关的微库,这为同构概念的初步尝试提供了第一步。
让我们考虑如何在lib.js
文件中编写URL解析库。 首先,我们将检测代码在哪里运行:
// running on Node.js?
var isNode = (typeof module === 'object' && module.exports);
这并不是特别健壮,因为您可以在客户端定义一个module.exports
函数,但我不知道有更好的方法(欢迎提出建议) 。 其他开发人员使用的类似方法是测试window
对象的存在:
// running on Node.js?
var isNode = typeof window === 'undefined';
现在,使用URLparse
函数完成我们的lib.js代码:
// lib.js library functions
// running on Node.js?
var isNode = (typeof module === 'object' && module.exports);
(function(lib) {
"use strict";
// require Node URL API
var url = (isNode ? require('url') : null);
// parse URL
lib.URLparse = function(str) {
if (isNode) {
return url.parse(str);
}
else {
url = document.createElement('a');
url.href = str;
return url;
}
}
})(isNode ? module.exports : this.lib = {});
在此代码中,为清楚起见,我使用了isNode
变量。 但是,可以通过将测试直接放在代码段的最后一个括号内来避免这种情况。
服务器端, URLparse
被导出为Common.JS模块。 要使用它:
// include lib.js module
var lib = require('./lib.js');
var url = lib.URLparse('http://site.com:81/path/page?a=1&b=2#hash');
console.log(
url.href + '\n' + // the full URL
url.protocol + '\n' + // http:
url.hostname + '\n' + // site.com
url.port + '\n' + // 81
url.pathname + '\n' + // /path/page
url.search + '\n' + // ?a=1&b=2
url.hash // #hash
);
客户端将URLparse
作为方法添加到全局lib
对象:
<script src="./lib.js"></script>
<script>
var url = lib.URLparse('http://site.com:81/path/page?a=1&b=2#hash');
console.log(
url.href + '\n' + // the full URL
url.protocol + '\n' + // http:
url.hostname + '\n' + // site.com
url.port + '\n' + // 81
url.pathname + '\n' + // /path/page
url.search + '\n' + // ?a=1&b=2
url.hash // #hash
);
</script>
除了库包含方法外,客户端和服务器API相同。
诚然,这是一个简单的示例, URLparse
在客户端和服务器上运行(大部分)单独的代码。 但是我们已经实现了一致的API,它说明了如何编写JavaScript代码以在任何地方运行。 我们可以扩展该库,以提供更多的客户端/服务器实用程序功能,例如字段验证,cookie解析,日期处理,货币格式等。
考虑到客户端和服务器上所需的逻辑类型不同,我不认为完全同构的应用程序是否可行或可行。 但是,与环境无关的库可以减轻必须编写两组代码来完成相同操作的痛苦。
From: https://www.sitepoint.com/url-parsing-isomorphic-javascript/