How to use global URLSearchParams in node

Viewed 41426

I am writing a (client-side) JavaScript library (a node/angular module). In this library, I make use of the URLSearchParams class.

const form = new URLSearchParams();
form.set('username', data.username);
form.set('password', data.pass);

As this is a shared library, it is packed as an npm module. However, when running a mocha unit test, I get the error that URLSearchParams is not defined. The reason seems to be that node does not have URLSearchParams at the global scope, but has to be imported using require('url'):

$ node
> new URLSearchParams()
ReferenceError: URLSearchParams is not defined
    at repl:1:5
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:73:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:340:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:538:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)

How can I make URLSearchParams available to the client-side code within node, so that I can test the library using mocha?

This is not working:

> global.URLSearchParams = require('url').URLSearchParams
undefined
> new URLSearchParams()
TypeError: URLSearchParams is not a constructor
    at repl:1:1
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:73:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:340:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:538:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)
4 Answers

In AWS Lambda which uses Node8.10, I had to do:

const {URLSearchParams} = require('url')
const sp = new URLSearchParams(request.querystring)

or

const url = require('url')
const sp = new url.URLSearchParams(request.querystring)

If we want to support big range of nodejs versions in our application , we could use some dirty code like this :

if(typeof URLSearchParams === 'undefined'){
    URLSearchParams = require('url').URLSearchParams;
}

Note: It is not best practice to require with a condition.

You may use polifill @ungap/url-search-params https://www.npmjs.com/package/@ungap/url-search-params and for webpack may use @ungap/url-search-params/cjs

Old NodeJS 8 (which isused in AWS and GCloud) does not support URLSearchParams so this polifill helps.

In Node 10 when using TypeScript you may enable library dom which includes URLSearchParams implementation. Change tsconfig.json:

{
  "compilerOptions": {
    "lib": [
      ...
      "dom"
      ...
    ]
  }
}
Related