url-parse vs url-parse vs url-join vs url-parse-lax
JavaScript URL 拼接与解析工具包对比
url-parseurl-parseurl-joinurl-parse-lax类似的npm包:

JavaScript URL 拼接与解析工具包对比

url-joinurl-parseurl-parse-lax 是 JavaScript 生态中处理 URL 的常用工具包,各自解决不同层面的问题。url-join 专注于安全地拼接多个 URL 片段,自动处理多余的斜杠;url-parse 提供严格的完整 URL 解析能力,将 URL 字符串分解为结构化对象;url-parse-lax 则是对 url-parse 的补充,用于解析不完整或相对 URL(如 /api/data),这些在 url-parse 中会因格式不完整而失败。这三个包常在实际项目中配合使用:先用 url-join 构造路径,再用 url-parseurl-parse-lax 解析结果以进一步操作。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
url-parse33,377,7841,03963 kB14-MIT
url-parse33,377,7841,03963 kB14-MIT
url-join14,292,3603654.74 kB5-MIT
url-parse-lax0555.24 kB06 个月前MIT

URL 拼接与解析工具深度对比:url-join、url-parse 与 url-parse-lax

在前端开发中,处理 URL 是常见但容易出错的任务。无论是拼接 API 路径、解析查询参数,还是安全地组合动态 URL,都需要可靠且语义清晰的工具。url-joinurl-parseurl-parse-lax 各司其职 —— 一个专注拼接,两个专注解析(但策略不同)。本文将从真实工程场景出发,深入比较它们的能力边界、行为差异和适用场景。

🧩 核心职责:拼接 vs 解析

首先明确一点:url-join 只做拼接,url-parseurl-parse-lax 只做解析。它们不是互斥替代品,而是互补工具。很多项目会同时使用 url-join(构造 URL)和 url-parse(拆解 URL)。

url-join:安全拼接路径片段

url-join 的唯一目标是把多个字符串安全地拼成一个合法 URL 路径,自动处理多余的斜杠。

// url-join 示例
import urljoin from 'url-join';

const baseUrl = 'https://api.example.com/v1/';
const endpoint = '/users/';
const id = '123/';

const fullUrl = urljoin(baseUrl, endpoint, id);
// 结果: 'https://api.example.com/v1/users/123'

它不会解析协议、主机或查询参数 —— 它只关心路径部分的拼接逻辑。

url-parse:严格解析完整 URL

url-parse 将一个完整 URL 字符串解析为结构化对象,包含协议、主机、路径、查询等字段。

// url-parse 示例
import Url from 'url-parse';

const url = new Url('https://user:pass@example.com:8080/path?query=123#frag');

console.log(url.protocol); // 'https:'
console.log(url.hostname);  // 'example.com'
console.log(url.pathname); // '/path'
console.log(url.query);    // '?query=123'

它遵循 WHATWG URL 标准,对输入格式要求严格。

url-parse-lax:宽松解析相对 URL

url-parse-lax 实际上是 url-parse 的一个包装器,专门用于解析不完整或相对 URL(如 /api/data../images/logo.png),这些在 url-parse 中会报错。

// url-parse-lax 示例
import urlParseLax from 'url-parse-lax';

// 这个相对路径在 url-parse 中会抛出错误
const relative = '/api/users?page=2';
const parsed = urlParseLax(relative);

console.log(parsed.pathname); // '/api/users'
console.log(parsed.query);    // '?page=2'

注意:url-parse-lax 内部调用 url-parse,所以它的输出结构与 url-parse 完全一致。

⚠️ 行为差异:面对非法输入时的表现

这是三者最关键的区分点。让我们用几个典型“坏”输入测试它们的行为。

场景 1:拼接包含查询参数的片段

// url-join
urljoin('https://api.com', '/users?id=1', 'profile');
// 结果: 'https://api.com/users?id=1/profile' ← 查询参数被当作路径一部分!

url-join 不理解查询参数,它把所有输入都视为路径片段。如果你需要保留查询参数,应先用 url-parse 拆解,修改路径后再重组。

场景 2:解析相对路径

// url-parse(直接调用)
new Url('/api/data'); 
// 抛出错误:Invalid URL

// url-parse-lax
urlParseLax('/api/data');
// 成功返回解析对象,hostname 为 null,pathname 为 '/api/data'

url-parse 要求输入必须是完整 URL(含协议),而 url-parse-lax 通过预处理(在前面加 http://n)使其能被解析,再清理掉伪造的协议和主机。

场景 3:拼接末尾带斜杠的路径

// url-join
urljoin('https://site.com/', '/api/', '/v1');
// 结果: 'https://site.com/api/v1' ← 自动去重斜杠

// 手动拼接(反面教材)
'https://site.com/' + '/api/' + '/v1';
// 结果: 'https://site.com//api//v1' ← 多余斜杠导致路径错误

url-join 的核心价值就在于此:避免手动拼接产生的路径错误。

🔧 典型工程场景与选型建议

场景 A:构建 API 请求 URL

你有一个基础 API 地址 https://api.service.com/v2/,需要动态拼接资源路径如 users/123/posts

推荐方案url-join

const apiUrl = urljoin('https://api.service.com/v2/', 'users', userId, 'posts');
// 安全生成: https://api.service.com/v2/users/123/posts

不要用模板字符串或 + 拼接,容易因多余斜杠出错。

场景 B:解析当前页面 URL 提取参数

你需要从 window.location.href 中提取查询参数或路径段。

推荐方案url-parse

const currentUrl = new Url(window.location.href);
const page = new URLSearchParams(currentUrl.query).get('page');

因为 window.location.href 总是完整 URL,url-parse 能正确解析。

场景 C:处理用户输入的相对路径

你的应用允许用户配置 API 前缀,可能输入 /my-api../proxy

推荐方案url-parse-lax

const userInput = '/my-api';
const parsed = urlParseLax(userInput);
// 安全获取 pathname: '/my-api'

若用 url-parse,会因缺少协议而崩溃。

场景 D:修改现有 URL 的路径部分

你有一个完整 URL https://old.com/data?sort=asc,想把路径换成 /new-data,保留查询参数。

推荐方案url-parse + 手动重组

const oldUrl = new Url('https://old.com/data?sort=asc');
oldUrl.set('pathname', '/new-data');
const newUrl = oldUrl.toString();
// 结果: 'https://old.com/new-data?sort=asc'

url-join 无法做到这一点,因为它不保留原始查询参数。

📌 总结:各司其职,按需组合

包名核心能力输入要求典型用途
url-join安全拼接路径任意字符串片段构造 API 路径、资源 URL
url-parse严格解析完整 URL必须含协议的完整 URL解析浏览器地址、外部链接
url-parse-lax宽松解析相对 URL相对路径或不完整 URL处理用户配置、内部路由片段

💡 重要提示url-parse 在 npm 上被列出两次(列表中有重复),但它是一个包。url-parse-lax 依赖 url-parse,所以两者常一起使用。

🛠 最佳实践组合示例

假设你要实现一个通用的 URL 构造器,支持基础 URL、路径片段和查询参数:

import urljoin from 'url-join';
import Url from 'url-parse';

function buildUrl(base, pathSegments, queryParams = {}) {
  // 1. 用 url-join 拼接路径
  const fullPath = urljoin(base, ...pathSegments);
  
  // 2. 用 url-parse 解析完整 URL
  const url = new Url(fullPath, true); // true 表示解析查询参数
  
  // 3. 合并查询参数
  url.set('query', { ...url.query, ...queryParams });
  
  return url.toString();
}

// 使用
buildUrl('https://api.com/', ['users', '123'], { expand: 'profile' });
// 结果: 'https://api.com/users/123?expand=profile'

这种组合充分发挥了各工具的优势:url-join 处理路径拼接,url-parse 处理查询参数和最终格式化。

❌ 不要这样用

  • 不要用 url-join 拼接查询参数:它会把 ?key=value 当作路径。
  • 不要用 url-parse 解析相对路径:会直接报错。
  • 不要用 url-parse-lax 处理完整 URL:虽然能工作,但没必要,直接用 url-parse 更清晰。

💡 最终建议

  • 如果你只需要拼接路径 → 选 url-join
  • 如果你总是处理完整 URL(如来自 location.href 或 API 响应)→ 选 url-parse
  • 如果你需要处理用户输入的相对路径或不完整 URL → 选 url-parse-lax

在复杂应用中,这三者往往共存 —— 它们解决的是 URL 生命周期中不同阶段的问题。理解它们的边界,才能写出健壮、可维护的 URL 处理逻辑。

如何选择: url-parse vs url-parse vs url-join vs url-parse-lax

  • url-parse:

    选择 url-parse 如果你需要解析完整的、符合标准的 URL(如 https://example.com/path?query=1),它能将其拆解为协议、主机、路径、查询等结构化字段。它要求输入必须包含协议(如 http:),否则会抛出错误。适用于处理浏览器地址栏 URL、API 返回的完整链接或任何已知格式正确的 URL。

  • url-parse:

    选择 url-parse 如果你需要解析完整的、符合标准的 URL(如 https://example.com/path?query=1),它能将其拆解为协议、主机、路径、查询等结构化字段。它要求输入必须包含协议(如 http:),否则会抛出错误。适用于处理浏览器地址栏 URL、API 返回的完整链接或任何已知格式正确的 URL。

  • url-join:

    选择 url-join 如果你需要安全地拼接多个 URL 路径片段(如基础 API 地址和资源路径),它能自动处理多余的斜杠,避免手动拼接导致的路径错误。它不处理查询参数或协议,仅专注于路径拼接,适合构造 API 请求 URL 或静态资源路径。不要用它来拼接包含查询参数的字符串,因为它会将 ?# 视为普通路径字符。

  • url-parse-lax:

    选择 url-parse-lax 如果你需要解析不完整或相对 URL(如 /api/users../images/logo.png?page=2),这些输入在 url-parse 中会失败。它内部使用 url-parse,但通过预处理使相对路径能被解析,输出结构与 url-parse 一致。适合处理用户配置、内部路由定义或任何来源不可控的 URL 片段。注意:对于已知完整的 URL,直接使用 url-parse 更清晰。

url-parse的README

url-parse

Version npmBuild StatusCoverage Status

Sauce Test Status

url-parse was created in 2014 when the WHATWG URL API was not available in Node.js and the URL interface was supported only in some browsers. Today this is no longer true. The URL interface is available in all supported Node.js release lines and basically all browsers. Consider using it for better security and accuracy.

The url-parse method exposes two different API interfaces. The url interface that you know from Node.js and the new URL interface that is available in the latest browsers.

In version 0.1 we moved from a DOM based parsing solution, using the <a> element, to a full Regular Expression solution. The main reason for this was to make the URL parser available in different JavaScript environments as you don't always have access to the DOM. An example of such environment is the Worker interface. The RegExp based solution didn't work well as it required a lot of lookups causing major problems in FireFox. In version 1.0.0 we ditched the RegExp based solution in favor of a pure string parsing solution which chops up the URL into smaller pieces. This module still has a really small footprint as it has been designed to be used on the client side.

In addition to URL parsing we also expose the bundled querystringify module.

Installation

This module is designed to be used using either browserify or Node.js it's released in the public npm registry and can be installed using:

npm install url-parse

Usage

All examples assume that this library is bootstrapped using:

'use strict';

var Url = require('url-parse');

To parse an URL simply call the URL method with the URL that needs to be transformed into an object.

var url = new Url('https://github.com/foo/bar');

The new keyword is optional but it will save you an extra function invocation. The constructor takes the following arguments:

  • url (String): A string representing an absolute or relative URL.
  • baseURL (Object | String): An object or string representing the base URL to use in case url is a relative URL. This argument is optional and defaults to location in the browser.
  • parser (Boolean | Function): This argument is optional and specifies how to parse the query string. By default it is false so the query string is not parsed. If you pass true the query string is parsed using the embedded querystringify module. If you pass a function the query string will be parsed using this function.

As said above we also support the Node.js interface so you can also use the library in this way:

'use strict';

var parse = require('url-parse')
  , url = parse('https://github.com/foo/bar', true);

The returned url instance contains the following properties:

  • protocol: The protocol scheme of the URL (e.g. http:).
  • slashes: A boolean which indicates whether the protocol is followed by two forward slashes (//).
  • auth: Authentication information portion (e.g. username:password).
  • username: Username of basic authentication.
  • password: Password of basic authentication.
  • host: Host name with port number. The hostname might be invalid.
  • hostname: Host name without port number. This might be an invalid hostname.
  • port: Optional port number.
  • pathname: URL path.
  • query: Parsed object containing query string, unless parsing is set to false.
  • hash: The "fragment" portion of the URL including the pound-sign (#).
  • href: The full URL.
  • origin: The origin of the URL.

Note that when url-parse is used in a browser environment, it will default to using the browser's current window location as the base URL when parsing all inputs. To parse an input independently of the browser's current URL (e.g. for functionality parity with the library in a Node environment), pass an empty location object as the second parameter:

var parse = require('url-parse');
parse('hostname', {});

Url.set(key, value)

A simple helper function to change parts of the URL and propagating it through all properties. When you set a new host you want the same value to be applied to port if has a different port number, hostname so it has a correct name again and href so you have a complete URL.

var parsed = parse('http://google.com/parse-things');

parsed.set('hostname', 'yahoo.com');
console.log(parsed.href); // http://yahoo.com/parse-things

It's aware of default ports so you cannot set a port 80 on an URL which has http as protocol.

Url.toString()

The returned url object comes with a custom toString method which will generate a full URL again when called. The method accepts an extra function which will stringify the query string for you. If you don't supply a function we will use our default method.

var location = url.toString(); // http://example.com/whatever/?qs=32

You would rarely need to use this method as the full URL is also available as href property. If you are using the URL.set method to make changes, this will automatically update.

Testing

The testing of this module is done in 3 different ways:

  1. We have unit tests that run under Node.js. You can run these tests with the npm test command.
  2. Code coverage can be run manually using npm run coverage.
  3. For browser testing we use Sauce Labs and zuul. You can run browser tests using the npm run test-browser command.

License

MIT

url-parse的README

url-parse

Version npmBuild StatusCoverage Status

Sauce Test Status

url-parse was created in 2014 when the WHATWG URL API was not available in Node.js and the URL interface was supported only in some browsers. Today this is no longer true. The URL interface is available in all supported Node.js release lines and basically all browsers. Consider using it for better security and accuracy.

The url-parse method exposes two different API interfaces. The url interface that you know from Node.js and the new URL interface that is available in the latest browsers.

In version 0.1 we moved from a DOM based parsing solution, using the <a> element, to a full Regular Expression solution. The main reason for this was to make the URL parser available in different JavaScript environments as you don't always have access to the DOM. An example of such environment is the Worker interface. The RegExp based solution didn't work well as it required a lot of lookups causing major problems in FireFox. In version 1.0.0 we ditched the RegExp based solution in favor of a pure string parsing solution which chops up the URL into smaller pieces. This module still has a really small footprint as it has been designed to be used on the client side.

In addition to URL parsing we also expose the bundled querystringify module.

Installation

This module is designed to be used using either browserify or Node.js it's released in the public npm registry and can be installed using:

npm install url-parse

Usage

All examples assume that this library is bootstrapped using:

'use strict';

var Url = require('url-parse');

To parse an URL simply call the URL method with the URL that needs to be transformed into an object.

var url = new Url('https://github.com/foo/bar');

The new keyword is optional but it will save you an extra function invocation. The constructor takes the following arguments:

  • url (String): A string representing an absolute or relative URL.
  • baseURL (Object | String): An object or string representing the base URL to use in case url is a relative URL. This argument is optional and defaults to location in the browser.
  • parser (Boolean | Function): This argument is optional and specifies how to parse the query string. By default it is false so the query string is not parsed. If you pass true the query string is parsed using the embedded querystringify module. If you pass a function the query string will be parsed using this function.

As said above we also support the Node.js interface so you can also use the library in this way:

'use strict';

var parse = require('url-parse')
  , url = parse('https://github.com/foo/bar', true);

The returned url instance contains the following properties:

  • protocol: The protocol scheme of the URL (e.g. http:).
  • slashes: A boolean which indicates whether the protocol is followed by two forward slashes (//).
  • auth: Authentication information portion (e.g. username:password).
  • username: Username of basic authentication.
  • password: Password of basic authentication.
  • host: Host name with port number. The hostname might be invalid.
  • hostname: Host name without port number. This might be an invalid hostname.
  • port: Optional port number.
  • pathname: URL path.
  • query: Parsed object containing query string, unless parsing is set to false.
  • hash: The "fragment" portion of the URL including the pound-sign (#).
  • href: The full URL.
  • origin: The origin of the URL.

Note that when url-parse is used in a browser environment, it will default to using the browser's current window location as the base URL when parsing all inputs. To parse an input independently of the browser's current URL (e.g. for functionality parity with the library in a Node environment), pass an empty location object as the second parameter:

var parse = require('url-parse');
parse('hostname', {});

Url.set(key, value)

A simple helper function to change parts of the URL and propagating it through all properties. When you set a new host you want the same value to be applied to port if has a different port number, hostname so it has a correct name again and href so you have a complete URL.

var parsed = parse('http://google.com/parse-things');

parsed.set('hostname', 'yahoo.com');
console.log(parsed.href); // http://yahoo.com/parse-things

It's aware of default ports so you cannot set a port 80 on an URL which has http as protocol.

Url.toString()

The returned url object comes with a custom toString method which will generate a full URL again when called. The method accepts an extra function which will stringify the query string for you. If you don't supply a function we will use our default method.

var location = url.toString(); // http://example.com/whatever/?qs=32

You would rarely need to use this method as the full URL is also available as href property. If you are using the URL.set method to make changes, this will automatically update.

Testing

The testing of this module is done in 3 different ways:

  1. We have unit tests that run under Node.js. You can run these tests with the npm test command.
  2. Code coverage can be run manually using npm run coverage.
  3. For browser testing we use Sauce Labs and zuul. You can run browser tests using the npm run test-browser command.

License

MIT