Create Dynamic URLs with URL Constructor in JavaScript
Tags: frontend, webdev, javascript, tutorial
Published: 2023-04-18 08:12:29

In web development, one of the essential components of building a frontend web application is constructing URLs dynamically. Creating clean and consistent URLs is crucial for both search engine optimization and user experience. JavaScript provides the URL constructor as a built-in class, to create and maintain dynamic URLs without having to hard-code them every time. In this article, we will explore what a URL constructor is, different components/parts of a URL, and how to use a URL constructor to build dynamic URLs.

## Prerequisite

To understand this article, you should have a basic knowledge of JavaScript and ES6 syntax.

## URL Constructor

The URL Constructor is a built-in JavaScript object that allows us to create a URL object from a string. The URL object provides methods to access and manipulate the different components of a URL, such as the hostname, protocol, pathname, and query parameters. To create a URL object, we simply instantiate it with the [**new operator**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new), passing in the URL string as an argument:

```jsx
new URL(url, base)
// OR
new URL(url)
```

* `url` is the full URL or path only if base is not provided.
    
* `base` is a string representing the base URL.
    

When both `base` and `url` arguments are provided, then the URL will be generated relative to the `base`.

```jsx
new URL("/tools", "https://www.asyncapi.com")
// https://www.asyncapi.com/tools
```

Before diving more into URL constructor, let’s first go over the components of a URL.

## Components of a URL

URLs are composed of several components, each of which plays a specific role in identifying and locating the resource. Taking the below URL as an example:

![Components of a URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ek746j4x2mdrzakdm9o3.png)

### Scheme

The first part of a URL is the scheme, and it specifies the protocol that will be used to access a resource. Some common schemes are `http` and `https`. Our sample URL uses the `https` scheme.

### Host

The host is the domain name or IP address that identifies where the resource is located. In our example, the host is `www.asyncapi.com`.

The combination of a `scheme` and `host` forms the `base` argument of a URL constructor.

### Path or Pathname

The path specifies the location of the resource. It typically consists of a series of directories separated by slashes. In our example, the path is `/tool`.

The `path` is the first argument provided to the URL constructor if a `base` argument is provided.

### Query String or Search

The query string is an optional part of the URL that contains data to be parsed as parameters. The query string begins with a question mark (`?`) and consists of one or more key-value pairs separated by ampersands (`&`). In our example, the query string is `langs=JavaScript&techs=Node.js`.

### Hash or Document Fragment

[**The hash**](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#document_fragments) is an optional part of the URL that identifies a specific section of the resource. It begins with a hash (`#`) and is often used with HTML pages to link to specific sections of the page. In our example, the hash is `Converters`.

## Modifying a URL

The URL Constructor also allows us to modify a URL by changing its components. We can use the same URL object methods to set new values to the different components. The most common component is modify is the `query string`.

The URL object has a searchParams property that returns a URLSearchParams object. The searchParams property can be used to build dynamic key-value pairs of a query string. Some common method that can be used include:

* `get(name)` - get a key by name
    
* `set(name, value)` - replace/set a key by name
    
* `append(name, value)` - add a key by name
    
* `delete(name)` - remove a key by name
    

The query string in our previous URL, [https://www.asyncapi.com/tools?langs=JavaScript&techs=Node.js#Converters](https://www.asyncapi.com/tools?langs=JavaScript&techs=Node.js#Converters) can be created like this:

```jsx
// instantiate a new URL object
const url = new URL("/tools", "https://www.asyncapi.com");
// build the query string
url.searchParams.set("langs", "JavaScript");
url.searchParams.set("techs", "Node.js");

console.log(url.toString());
// https://www.asyncapi.com/tools?langs=JavaScript&techs=Node.js
```

An [**URLSearchParams**](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object instance can also be used to create to build the query string. We won’t be using the `base` and `url` argument in this case:

```jsx
let query = new URLSearchParams();
query.set("langs", "JavaScript");
query.set("techs", "Node.js");

console.log(query.toString());
// langs=JavaScript&techs=Node.js
```

## Why Use URL and URLSearchParams

### Validity
When working with URLs, it's important to ensure that they are valid and conform to the proper syntax. The `URL` and `URLSearchParams` objects automatically encode and decode special characters(spaces, +, &, e.t.c) in URLs, and can help prevent syntax errors and other issues. Consider this query string:
```jsx
tech=Spring Cloud Streams
langs=C/C++
```
Constructing this query string with pure string will definitely break the URL because URL shouldn’t have spaces:
```jsx
let url = "https://www.asyncapi.com/tools?techs=Spring Cloud Streams&langs=C/C++";
```
The easiest way to construct this is to use the `URL` and `URLSearchParams`.
- Using `URL`
```jsx
let url = new URL("https://www.asyncapi.com/tools");
url.searchParams.set("techs", "Spring Cloud Streams");
url.searchParams.set("langs", "C/C++");
```
Then use the `toString()` method provided by `URL` to get the full URL.
```jsx
console.log(url.toString())
// https://www.asyncapi.com/tools?techs=Spring+Cloud+Streams&langs=C%2FC%2B%2B
```

- Using `URLSearchParams`
```jsx
let url = new URL("https://www.asyncapi.com/tools?");
let query = new URLSearchParams();
query.set("tech", "Spring Cloud Streams")
query.set("langs", "C/C++")

let fullUrl = `${url}${query.toString()}`;
console.log(fullUrl);
// https://www.asyncapi.com/tools?techs=Spring+Cloud+Streams&langs=C%2FC%2B%2B
```

`URLSearchParams` really shines when building a filter option for a page, e.g a search page. I made use of it in [one of my Pull Requests](https://github.com/asyncapi/website/commit/88f5f9127875ad3655a56890383f8325da0c58c5#diff-b3bcf2dc7af96910c7a1e7b699d660110e17b511dae82e6284356c2389d47ba0R60) on [AsyncAPI repo](https://github.com/asyncapi). URLSearchParams made sure the filter options are encoded before adding it to the page URL.

### Readability
Apart from avoiding issues, using URL and URLSearchParams constructors improve code readability. It’s clear what path and query string we are building.
```jsx
// set the base and path
const url = new URL("/tools", "https://www.asyncapi.com");

// build the query string
url.searchParams.set("langs", "JavaScript");
url.searchParams.set("techs", "Node.js");

if(true) {
  url.searchParams.delete("langs");
}

//
```

## Conclusion

URL constructors and URLSearchParams are powerful tools that make it easier to build dynamic URLs in JavaScript. They automatically encode and decode special characters to avoid syntax errors, and provide a readable way to build query strings. By using these tools, you can create clean and consistent URLs that are essential for search engine optimization and user experience.

You can read the following articles to learn more about `URL` and `URLSearchParams`:

* [**URL**](https://developer.mozilla.org/en-US/docs/Web/API/URL) from MDN
    
* [**URL Objects**](https://javascript.info/url) from [Javascript.info](http://Javascript.info)
    
* [**URLSearchParams**](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) from MDN