query-string vs url-parse vs url-parse-lax vs url-search-params-polyfill
URL 解析与查询字符串管理方案对比
query-stringurl-parseurl-parse-laxurl-search-params-polyfill类似的npm包:

URL 解析与查询字符串管理方案对比

query-stringurl-parse 是前端处理 URL 和查询参数的常用工具库,而 url-parse-laxurl-search-params-polyfill 则是针对特定旧环境的历史方案。随着现代浏览器和 Node.js 对原生 URLURLSearchParams API 的完善支持,开发者需要明确何时使用第三方库,何时直接采用标准 API。本文将对这四个包进行深度技术对比,帮助你在架构选型时做出合理决策。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
query-string06,90859.1 kB21 个月前MIT
url-parse01,03463 kB16-MIT
url-parse-lax0555.24 kB01 年前MIT
url-search-params-polyfill060017.4 kB33 年前MIT

URL 解析与查询字符串管理方案对比

在前端架构中,处理 URL 和查询参数是常见需求。虽然现代环境提供了原生 API,但 query-stringurl-parse 等库依然活跃。与此同时,url-parse-laxurl-search-params-polyfill 代表了过去的解决方案。本文将深入对比它们的技术细节,帮助你避开技术债务。

🧩 核心功能:查询字符串解析

处理查询参数(如 ?id=1&tag=js)时,原生 URLSearchParamsquery-string 是最常见的选择。

query-string 提供了丰富的配置选项,支持数组格式化和排序控制。

import queryString from 'query-string';

const params = queryString.parse('?tags[]=js&tags[]=node', {
  arrayFormat: 'bracket'
});
// 输出:{ tags: ['js', 'node'] }

const str = queryString.stringify({ tags: ['js', 'node'] }, {
  arrayFormat: 'bracket'
});
// 输出:'tags%5B%5D=js&tags%5B%5D=node'

url-search-params-polyfill (及原生 API) 主要用于标准键值对,对数组支持较弱。

// 原生 API 或 polyfill
const params = new URLSearchParams('?tags=js&tags=node');
// 输出:getAll('tags') -> ['js', 'node']

// 序列化数组需要手动处理
const params = new URLSearchParams();
params.append('tags', 'js');
params.append('tags', 'node');
// 输出:'tags=js&tags=node' (无括号格式)

对比结论:如果你的后端严格要求 tags[]=js 这种格式,query-string 更省心。如果只是简单键值对,原生 API 足够。

🌐 核心功能:完整 URL 解析

解析完整 URL(包含协议、主机、路径)时,url-parse 和原生 URL 是主要选项。

url-parse 允许直接修改属性,无需创建新对象。

import UrlParse from 'url-parse';

const url = new UrlParse('https://example.com/path');
url.set('port', '8080');
url.set('query', { id: 1 });

console.log(url.toString());
// 输出:'https://example.com:8080/path?id=1'

url-parse-lax 旨在兼容旧版 Node 的 url.parse,允许缺少协议的 URL。

import urlParseLax from 'url-parse-lax';

// 允许不带协议的 URL
const url = urlParseLax('//example.com/path');
console.log(url.protocol);
// 输出:'https:' (自动补全)

原生 URL 现在已支持协议相对 URL,且不可变。

// 原生 API
const url = new URL('/path', 'https://example.com');
url.port = '8080';
// 注意:原生对象修改后需重新 toString

对比结论url-parse 的可变接口在循环修改场景下代码更少。但原生 URL 性能更好且无依赖。url-parse-lax 的功能已被原生 API 覆盖。

⚠️ 遗留与废弃包警告

在架构选型中,识别何时使用某个包同样重要。

1. url-parse-lax:历史遗留问题

该包主要为了解决 Node.js 旧版 url 模块无法解析 //example.com 的问题。现在 new URL() 已完美支持。

// ❌ 旧方案:依赖第三方库
import urlParseLax from 'url-parse-lax';
const oldWay = urlParseLax('//example.com');

// ✅ 新方案:原生支持
const newWay = new URL('//example.com', location.href);

建议:新项目严禁使用 url-parse-lax,直接迁移至原生 URL

2. url-search-params-polyfill:原生已普及

该包用于在不支持 URLSearchParams 的环境(如 IE11)中提供支持。随着 IE 停止维护,其价值已归零。

// ❌ 旧方案:引入 polyfill
import 'url-search-params-polyfill';
const params = new URLSearchParams();

// ✅ 新方案:直接使用
const params = new URLSearchParams();

建议:除非你必须支持 IE11,否则不要安装此包。现代构建工具(如 Babel)可按需处理兼容性问题。

🛠️ 实际场景代码对比

场景:提取并修改当前页面参数

query-string 方案

import queryString from 'query-string';

const query = queryString.parse(window.location.search);
query.page = '2';
window.history.pushState('', '', '?' + queryString.stringify(query));

url-parse 方案

import UrlParse from 'url-parse';

const url = new UrlParse(window.location.href);
url.query = { ...url.query, page: '2' };
window.history.pushState('', '', url.toString());

原生 API 方案

const url = new URL(window.location.href);
url.searchParams.set('page', '2');
window.history.pushState('', '', url.toString());

分析:原生 API 代码最简洁且无依赖。query-string 在需要特定序列化格式时更有优势。url-parse 适合需要操作整个 URL 对象而非仅 search 参数的场景。

📊 总结表格

特性query-stringurl-parseurl-parse-laxurl-search-params-polyfill
主要用途查询字符串序列化/反序列化完整 URL 解析与修改兼容旧版 Node URL 解析旧浏览器支持 URLSearchParams
原生替代URLSearchParamsURLURLURLSearchParams
数组支持✅ 强大 (可配置格式)⚠️ 一般⚠️ 一般⚠️ 基础
修改方式不可变 (返回新字符串)可变 (直接修改属性)不可变可变
维护状态✅ 活跃✅ 活跃⚠️ 遗留❌ 过时
推荐指数⭐⭐⭐⭐⭐⭐⭐❌ 不推荐❌ 不推荐

💡 最终建议

在现代前端架构中,优先使用原生 URLURLSearchParams API。它们性能更好、无依赖且符合标准。

仅在以下情况考虑第三方库:

  1. 复杂查询格式:后端严格要求特定数组格式(如 arr[]=arr[0]=),query-string 的配置项能节省大量手动编码工作。
  2. 旧环境兼容:必须支持无法使用 Babel 转译的极旧环境(但这种情况已极少见)。
  3. 可变操作需求url-parse 的可变接口在某些动态构建 URL 的循环场景中代码更简洁。

避坑指南

  • 看到 url-parse-lax 请直接忽略,原生 URL 已解决问题。
  • 看到 url-search-params-polyfill 请检查目标用户浏览器占比,通常可直接移除。

选择工具时,始终问自己:“原生 API 真的做不到吗?” 大多数情况下,答案是肯定的。

如何选择: query-string vs url-parse vs url-parse-lax vs url-search-params-polyfill

  • query-string:

    选择 query-string 如果你需要处理复杂的查询字符串格式(如数组序列化、排序控制),或者需要在 Node.js 和浏览器之间保持完全一致的行为。它在处理边缘情况(如编码、分隔符)上比原生 API 更灵活,适合对 URL 格式有严格要求的 SSR 项目。

  • url-parse:

    选择 url-parse 如果你需要频繁修改 URL 的各个组成部分(如协议、主机、端口),且希望比原生 URL 对象更轻量或兼容旧版 Node 环境。它提供了可变的操作接口,适合需要动态构建或修改完整 URL 的场景。

  • url-parse-lax:

    不建议在新项目中使用。 该包旨在让 Node 旧版 url.parse 支持协议相对 URL,但原生 URL 类现已完美支持此功能。继续使用它会增加不必要的依赖,建议直接迁移至标准 new URL() API。

  • url-search-params-polyfill:

    不建议在新项目中使用。 现代浏览器和 Node.js 已原生支持 URLSearchParams,全球覆盖率极高。引入 polyfill 只会增加包体积且无实际收益,除非你需要支持已停止维护的 IE11 等旧环境。

query-string的README

query-string

Parse and stringify URL query strings

Install

npm install query-string

[!WARNING] Remember the hyphen! Do not install the deprecated querystring package!

For browser usage, this package targets the latest version of Chrome, Firefox, and Safari.

[!TIP] Consider using URLSearchParams for simple use cases. It's a native browser API that handles basic query string operations.

Usage

import queryString from 'query-string';

console.log(location.search);
//=> '?foo=bar'

const parsed = queryString.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}

console.log(location.hash);
//=> '#token=bada55cafe'

const parsedHash = queryString.parse(location.hash);
console.log(parsedHash);
//=> {token: 'bada55cafe'}

parsed.foo = 'unicorn';
parsed.ilike = 'pizza';

const stringified = queryString.stringify(parsed);
//=> 'foo=unicorn&ilike=pizza'

location.search = stringified;
// note that `location.search` automatically prepends a question mark
console.log(location.search);
//=> '?foo=unicorn&ilike=pizza'

API

.parse(string, options?)

Parse a query string into an object. Leading ? or # are ignored, so you can pass location.search or location.hash directly.

The returned object is created with Object.create(null) and thus does not have a prototype.

queryString.parse('?foo=bar');
//=> {foo: 'bar'}

queryString.parse('#token=secret&name=jhon');
//=> {token: 'secret', name: 'jhon'}

options

Type: object

decode

Type: boolean
Default: true

Decode the keys and values. URL components are decoded with decode-uri-component.

arrayFormat

Type: string
Default: 'none'

  • 'bracket': Parse arrays with bracket representation:
import queryString from 'query-string';

queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'});
//=> {foo: ['1', '2', '3']}
  • 'index': Parse arrays with index representation:
import queryString from 'query-string';

queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'});
//=> {foo: ['1', '2', '3']}
  • 'comma': Parse arrays with elements separated by comma:
import queryString from 'query-string';

queryString.parse('foo=1,2,3', {arrayFormat: 'comma'});
//=> {foo: ['1', '2', '3']}
  • 'separator': Parse arrays with elements separated by a custom character:
import queryString from 'query-string';

queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator: '|'});
//=> {foo: ['1', '2', '3']}
  • 'bracket-separator': Parse arrays (that are explicitly marked with brackets) with elements separated by a custom character:
import queryString from 'query-string';

queryString.parse('foo[]', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: []}

queryString.parse('foo[]=', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: ['']}

queryString.parse('foo[]=1', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: ['1']}

queryString.parse('foo[]=1|2|3', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: ['1', '2', '3']}

queryString.parse('foo[]=1||3|||6', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: ['1', '', 3, '', '', '6']}

queryString.parse('foo[]=1|2|3&bar=fluffy&baz[]=4', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> {foo: ['1', '2', '3'], bar: 'fluffy', baz:['4']}
  • 'colon-list-separator': Parse arrays with parameter names that are explicitly marked with :list:
import queryString from 'query-string';

queryString.parse('foo:list=one&foo:list=two', {arrayFormat: 'colon-list-separator'});
//=> {foo: ['one', 'two']}
  • 'none': Parse arrays with elements using duplicate keys:
import queryString from 'query-string';

queryString.parse('foo=1&foo=2&foo=3');
//=> {foo: ['1', '2', '3']}
arrayFormatSeparator

Type: string
Default: ','

The character used to separate array elements when using {arrayFormat: 'separator'}.

sort

Type: Function | boolean
Default: true

Supports both Function as a custom sorting function or false to disable sorting.

parseNumbers

Type: boolean
Default: false

import queryString from 'query-string';

queryString.parse('foo=1', {parseNumbers: true});
//=> {foo: 1}

Parse the value as a number type instead of string type if it's a number.

parseBooleans

Type: boolean
Default: false

import queryString from 'query-string';

queryString.parse('foo=true', {parseBooleans: true});
//=> {foo: true}

Parse the value as a boolean type instead of string type if it's a boolean.

types

Type: object
Default: {}

Specifies a schema for parsing query values with explicit type declarations. When defined, the types provided here take precedence over general parsing options such as parseNumbers, parseBooleans, and arrayFormat.

Use this option to explicitly define the type of a specific parameter—particularly useful in cases where the type might otherwise be ambiguous (e.g., phone numbers or IDs).

You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result. When used with array formats (like comma, separator, bracket, etc.), the function is applied to each array element individually.

Supported Types:

  • 'boolean': Parse flagged as a boolean (overriding the parseBooleans option):
queryString.parse('?isAdmin=true&flagged=true&isOkay=0', {
		parseBooleans: false,
		types: {
				flagged: 'boolean',
				isOkay: 'boolean',
		},
});
//=> {isAdmin: 'true', flagged: true, isOkay: false}

Note: The 'boolean' type also converts '0' and '1' to booleans, and treats valueless keys (e.g. ?flag) as true.

  • 'string': Parse phoneNumber as a string (overriding the parseNumbers option):
import queryString from 'query-string';

queryString.parse('?phoneNumber=%2B380951234567&id=1', {
	parseNumbers: true,
	types: {
		phoneNumber: 'string',
	}
});
//=> {phoneNumber: '+380951234567', id: 1}
  • 'number': Parse age as a number (even when parseNumbers is false):
import queryString from 'query-string';

queryString.parse('?age=20&id=01234&zipcode=90210', {
	types: {
		age: 'number',
	}
});
//=> {age: 20, id: '01234', zipcode: '90210'}
  • 'string[]': Parse items as an array of strings (overriding the parseNumbers option):
import queryString from 'query-string';

queryString.parse('?age=20&items=1%2C2%2C3', {
	parseNumbers: true,
	types: {
		items: 'string[]',
	}
});
//=> {age: 20, items: ['1', '2', '3']}
  • 'number[]': Parse items as an array of numbers (even when parseNumbers is false):
import queryString from 'query-string';

queryString.parse('?age=20&items=1%2C2%2C3', {
	types: {
		items: 'number[]',
	}
});
//=> {age: '20', items: [1, 2, 3]}
  • 'Function': Provide a custom function as the parameter type. The parameter's value will equal the function's return value. When used with array formats (like comma, separator, bracket, etc.), the function is applied to each array element individually.
import queryString from 'query-string';

queryString.parse('?age=20&id=01234&zipcode=90210', {
	types: {
		age: value => value * 2,
	}
});
//=> {age: 40, id: '01234', zipcode: '90210'}

// With arrays, the function is applied to each element
queryString.parse('?scores=10,20,30', {
	arrayFormat: 'comma',
	types: {
		scores: value => Number(value) * 2,
	}
});
//=> {scores: [20, 40, 60]}

NOTE: Array types (string[], number[]) are ignored if arrayFormat is set to 'none'.

queryString.parse('ids=001%2C002%2C003&foods=apple%2Corange%2Cmango', {
	arrayFormat: 'none',
	types: {
		ids: 'number[]',
		foods: 'string[]',
	},
}
//=> {ids:'001,002,003', foods:'apple,orange,mango'}
Function
import queryString from 'query-string';

queryString.parse('?age=20&id=01234&zipcode=90210', {
	types: {
		age: value => value * 2,
	}
});
//=> {age: 40, id: '01234', zipcode: '90210'}

Parse the value as a boolean type instead of string type if it's a boolean.

.stringify(object, options?)

Stringify an object into a query string and sorting the keys.

Supported value types: string, number, bigint, boolean, null, undefined, and arrays of these types. Other types like Symbol, functions, or objects (except arrays) will throw an error.

options

Type: object

strict

Type: boolean
Default: true

Strictly encode URI components. It uses encodeURIComponent if set to false. You probably don't care about this option.

encode

Type: boolean
Default: true

URL encode the keys and values.

arrayFormat

Type: string
Default: 'none'

  • 'bracket': Serialize arrays using bracket representation:
import queryString from 'query-string';

queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket'});
//=> 'foo[]=1&foo[]=2&foo[]=3'
  • 'index': Serialize arrays using index representation:
import queryString from 'query-string';

queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'index'});
//=> 'foo[0]=1&foo[1]=2&foo[2]=3'
  • 'comma': Serialize arrays by separating elements with comma:
import queryString from 'query-string';

queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'comma'});
//=> 'foo=1,2,3'

queryString.stringify({foo: [1, null, '']}, {arrayFormat: 'comma'});
//=> 'foo=1,,'
// Note that typing information for null values is lost
// and `.parse('foo=1,,')` would return `{foo: [1, '', '']}`.
  • 'separator': Serialize arrays by separating elements with a custom character:
import queryString from 'query-string';

queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'separator', arrayFormatSeparator: '|'});
//=> 'foo=1|2|3'
  • 'bracket-separator': Serialize arrays by explicitly post-fixing array names with brackets and separating elements with a custom character:
import queryString from 'query-string';

queryString.stringify({foo: []}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]'

queryString.stringify({foo: ['']}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]='

queryString.stringify({foo: [1]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]=1'

queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]=1|2|3'

queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]=1||3|||6'

queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|', skipNull: true});
//=> 'foo[]=1||3|6'

queryString.stringify({foo: [1, 2, 3], bar: 'fluffy', baz: [4]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
//=> 'foo[]=1|2|3&bar=fluffy&baz[]=4'
  • 'colon-list-separator': Serialize arrays with parameter names that are explicitly marked with :list:
import queryString from 'query-string';

queryString.stringify({foo: ['one', 'two']}, {arrayFormat: 'colon-list-separator'});
//=> 'foo:list=one&foo:list=two'
  • 'none': Serialize arrays by using duplicate keys:
import queryString from 'query-string';

queryString.stringify({foo: [1, 2, 3]});
//=> 'foo=1&foo=2&foo=3'
arrayFormatSeparator

Type: string
Default: ','

The character used to separate array elements when using {arrayFormat: 'separator'}.

sort

Type: Function | boolean

Supports both Function as a custom sorting function or false to disable sorting.

import queryString from 'query-string';

const order = ['c', 'a', 'b'];

queryString.stringify({a: 1, b: 2, c: 3}, {
	sort: (a, b) => order.indexOf(a) - order.indexOf(b)
});
//=> 'c=3&a=1&b=2'
import queryString from 'query-string';

queryString.stringify({b: 1, c: 2, a: 3}, {sort: false});
//=> 'b=1&c=2&a=3'

If omitted, keys are sorted using Array#sort(), which means, converting them to strings and comparing strings in Unicode code point order.

skipNull

Skip keys with null as the value.

Note that keys with undefined as the value are always skipped.

Type: boolean
Default: false

import queryString from 'query-string';

queryString.stringify({a: 1, b: undefined, c: null, d: 4}, {
	skipNull: true
});
//=> 'a=1&d=4'
import queryString from 'query-string';

queryString.stringify({a: undefined, b: null}, {
	skipNull: true
});
//=> ''
skipEmptyString

Skip keys with an empty string as the value.

Type: boolean
Default: false

import queryString from 'query-string';

queryString.stringify({a: 1, b: '', c: '', d: 4}, {
	skipEmptyString: true
});
//=> 'a=1&d=4'
import queryString from 'query-string';

queryString.stringify({a: '', b: ''}, {
	skipEmptyString: true
});
//=> ''
replacer

A function that transforms key-value pairs before stringification.

Type: function
Default: undefined

Similar to the replacer parameter of JSON.stringify(), this function is called for each key-value pair and can be used to transform values before they are stringified. The function receives the key and value, and should return the transformed value. Returning undefined will omit the key-value pair from the resulting query string.

This is useful for custom serialization of non-primitive types like Date:

import queryString from 'query-string';

queryString.stringify({
	date: new Date('2024-01-15T10:30:00Z'),
	name: 'John'
}, {
	replacer: (key, value) => {
		if (value instanceof Date) {
			return value.toISOString();
		}

		return value;
	}
});
//=> 'date=2024-01-15T10%3A30%3A00.000Z&name=John'

You can also use it to filter out keys:

import queryString from 'query-string';

queryString.stringify({
	a: 1,
	b: null,
	c: 3
}, {
	replacer: (key, value) => value === null ? undefined : value
});
//=> 'a=1&c=3'

.extract(string)

Extract a query string from a URL that can be passed into .parse().

queryString.extract('https://foo.bar?foo=bar');
//=> 'foo=bar'

.parseUrl(string, options?)

Extract the URL and the query string as an object.

Returns an object with a url and query property.

If the parseFragmentIdentifier option is true, the object will also contain a fragmentIdentifier property.

import queryString from 'query-string';

queryString.parseUrl('https://foo.bar?foo=bar');
//=> {url: 'https://foo.bar', query: {foo: 'bar'}}

queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true});
//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'}

options

Type: object

The options are the same as for .parse().

Extra options are as below.

parseFragmentIdentifier

Parse the fragment identifier from the URL.

Type: boolean
Default: false

import queryString from 'query-string';

queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true});
//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'}

.stringifyUrl(object, options?)

Stringify an object into a URL with a query string and sorting the keys. The inverse of .parseUrl()

The options are the same as for .stringify().

Returns a string with the URL and a query string.

Query items in the query property overrides queries in the url property.

The fragmentIdentifier property overrides the fragment identifier in the url property.

queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}});
//=> 'https://foo.bar?foo=bar'

queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}});
//=> 'https://foo.bar?foo=bar'

queryString.stringifyUrl({
	url: 'https://foo.bar',
	query: {
		top: 'foo'
	},
	fragmentIdentifier: 'bar'
});
//=> 'https://foo.bar?top=foo#bar'

object

Type: object

url

Type: string

The URL to stringify.

query

Type: object

Query items to add to the URL.

.pick(url, keys, options?)

.pick(url, filter, options?)

Pick query parameters from a URL.

Returns a string with the new URL.

import queryString from 'query-string';

queryString.pick('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?foo=1#hello'

queryString.pick('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?bar=2#hello'

.exclude(url, keys, options?)

.exclude(url, filter, options?)

Exclude query parameters from a URL.

Returns a string with the new URL.

import queryString from 'query-string';

queryString.exclude('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?bar=2#hello'

queryString.exclude('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?foo=1#hello'

url

Type: string

The URL containing the query parameters to filter.

keys

Type: string[]

The names of the query parameters to filter based on the function used.

filter

Type: (key, value) => boolean

A filter predicate that will be provided the name of each query parameter and its value. The parseNumbers and parseBooleans options also affect value.

options

Type: object

Parse options and stringify options.

Nesting

This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of edge cases.

You're much better off just converting the object to a JSON string:

import queryString from 'query-string';

queryString.stringify({
	foo: 'bar',
	nested: JSON.stringify({
		unicorn: 'cake'
	})
});
//=> 'foo=bar&nested=%7B%22unicorn%22%3A%22cake%22%7D'

However, there is support for multiple instances of the same key:

import queryString from 'query-string';

queryString.parse('likes=cake&name=bob&likes=icecream');
//=> {likes: ['cake', 'icecream'], name: 'bob'}

queryString.stringify({color: ['taupe', 'chartreuse'], id: '515'});
//=> 'color=taupe&color=chartreuse&id=515'

Falsy values

Sometimes you want to unset a key, or maybe just make it present without assigning a value to it. Here is how falsy values are stringified:

import queryString from 'query-string';

queryString.stringify({foo: false});
//=> 'foo=false'

queryString.stringify({foo: null});
//=> 'foo'

queryString.stringify({foo: undefined});
//=> ''

FAQ

Why is it parsing + as a space?

See this answer.