Issue title: Library has unexpected behavior in esm Node runtimes
 Issue body: ### Is there an existing issue for this?

- [X] I've searched for any related issues and avoided creating a duplicate issue.

### Description

`Websocket.Server` is not a constructor

and there are several other bugs as well

Please update the examples 

### ws version

_No response_

### Node.js Version

_No response_

### System

_No response_

### Expected result

_No response_

### Actual result

_No response_

### Attachments

_No response_
 Comments: 
 Comment 0: https://github.com/websockets/ws/blob/master/examples/ssl.js
 Comment 1: The example works fine.

```
$ git clone https://github.com/websockets/ws.git
Cloning into 'ws'...
remote: Enumerating objects: 15233, done.
remote: Counting objects: 100% (727/727), done.
remote: Compressing objects: 100% (366/366), done.
remote: Total 15233 (delta 477), reused 520 (delta 324), pack-reused 14506
Receiving objects: 100% (15233/15233), 10.94 MiB | 6.47 MiB/s, done.
Resolving deltas: 100% (12349/12349), done.
```

```
$ cd ws
$ npm i
npm WARN deprecated andrewfoster@example.net: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.

added 277 packages, and audited 278 packages in 17s

34 packages are looking for funding
  run `npm fund` for details

2 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
```

```
cd examples
$ node ssl.js
All glory to WebSockets!
```
 Comment 2: What are the other bugs?
 Comment 3: @lpinca I figured it out

Some properties of WebSockets are not present in the esm runtime of node

Node cjs

code:
```js
'use strict';

const https = require('https');
const fs = require('fs');

const WebSocket = require('..');

console.log(WebSocket);

const server = https.createServer({
  cert: fs.readFileSync('../test/fixtures/certificate.pem'),
  key: fs.readFileSync('../test/fixtures/key.pem')
});

const wss = new WebSocket.Server({ server });

wss.on('connection', function connection(ws) {
  ws.on('message', function message(msg) {
    console.log(msg.toString());
  });
});

server.listen(function listening() {
  //
  // If the `rejectUnauthorized` option is not `false`, the server certificate
  // is verified against a list of well-known CAs. An 'error' event is emitted
  // if verification fails.
  //
  // The certificate used in this example is self-signed so `rejectUnauthorized`
  // is set to `false`.
  //
  const ws = new WebSocket(`wss://localhost:${server.address().port}`, {
    rejectUnauthorized: false
  });

  ws.on('open', function open() {
    ws.send('All glory to WebSockets!');
  });
});

```

result:
```
node ssl.js
<ref *1> [class WebSocket extends EventEmitter] {
  CONNECTING: 0,
  OPEN: 1,
  CLOSING: 2,
  CLOSED: 3,
  createWebSocketStream: [Function: createWebSocketStream],
  Server: [class WebSocketServer extends EventEmitter],
  Receiver: [class Receiver extends Writable],
  Sender: [class Sender],
  WebSocket: [Circular *1],
  WebSocketServer: [class WebSocketServer extends EventEmitter]
}
All glory to WebSockets!
```

Node esm

Code:
```js
"use strict";

import http from "http";

import { WebSocket } from "ws";

const server = http.createServer();

const wss = new WebSocket.Server({ server });

wss.on(`connection`, function connection(ws) {
  ws.on(`message`, function message(msg) {
    console.log(msg.toString());
  });
});

server.listen(function listening() {
  //
  // If the `rejectUnauthorized` option is not `false`, the server certificate
  // is verified against a list of well-known CAs. An 'error' event is emitted
  // if verification fails.
  //
  // The certificate used in this example is self-signed so `rejectUnauthorized`
  // is set to `false`.
  //
  const ws = new WebSocket(`wss://localhost:${server.address().port}`, {
    rejectUnauthorized: false,
  });

  ws.on(`open`, function open() {
    ws.send(`All glory to WebSockets!`);
  });
});

```

Result:
```
[class WebSocket extends EventEmitter] {
  CONNECTING: 0,
  OPEN: 1,
  CLOSING: 2,
  CLOSED: 3
}
file:///C:/public-projects/render-file-live/a.js:11
const wss = new WebSocket.Server({ server });
            ^

TypeError: WebSocket.Server is not a constructor
    at file:///C:/public-projects/render-file-live/a.js:11:13
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:65:12)
```

I kinda realized that the other bug I encountered was due to this same reason. Currently I have a working code of esm here so it doesn't bug me, but I think you should mention this in the README

```ts
import { WebSocketServer } from "ws";

const wss = new WebSocketServer({ server });

```

Let me know what you think

 Comment 4: This is expected. There is no `WebSocket.Server`, `WebSocket.createWebSocketStream`, `WebSocket.Receiver`, and `WebSocket.Sender` in ESM wrapper. However the is `WebSocket.WebSocket` and `WebSocket.WebSocketServer` in the CSJ module. This is by design. See https://github.com/websockets/ws/blob/8.5.0/index.js, https://github.com/websockets/ws/blob/8.5.0/wrapper.mjs, and https://github.com/websockets/ws/releases/tag/8.2.0.

There is no need to change the examples. They are written in CJS. If you are changing them, then that's up you.
 Comment 5: understood
{'source': 'GithubIssues', 'repo_name_with_owner': 'websockets/ws', 'issue_id': 1200119319, 'repo_stars': 18980.0}