Skip to content

Commit 88b0ec7

Browse files
authored
perf: replace mime-types with mrmime (#22)
1 parent 832c0a4 commit 88b0ec7

7 files changed

Lines changed: 73 additions & 26 deletions

File tree

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"myhtml",
1818
"configurated",
1919
"mycustom",
20+
"mrmime",
2021
"commitlint",
2122
"nosniff",
2223
"deoptimize",

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Default: `undefined`
166166
This property allows a user to register custom mime types or extension mappings.
167167
eg. `mimeTypes: { phtml: 'text/html' }`.
168168

169-
Please see the documentation for [`mime-types`](https://github.com/jshttp/mime-types) for more information.
169+
Please see the documentation for [`mrmime`](https://github.com/lukeed/mrmime) for more information.
170170

171171
### mimeTypeDefault
172172

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
},
4141
"dependencies": {
4242
"memfs": "^4.43.1",
43-
"mime-types": "^3.0.1",
43+
"mrmime": "^2.0.1",
4444
"on-finished": "^2.4.1",
4545
"range-parser": "^1.2.1"
4646
},
@@ -55,7 +55,6 @@
5555
"@rstest/core": "0.9.2",
5656
"@types/connect": "^3.4.35",
5757
"@types/express": "^5.0.2",
58-
"@types/mime-types": "^3.0.1",
5958
"@types/node": "^22.3.0",
6059
"@types/on-finished": "^2.3.4",
6160
"@types/range-parser": "^1.2.7",

pnpm-lock.yaml

Lines changed: 9 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const mime = require("mime-types");
1+
const { mimes } = require("mrmime");
22

33
const middleware = require("./middleware");
44
const getFilenameFromUrl = require("./utils/getFilenameFromUrl");
@@ -203,12 +203,11 @@ function wdm(compiler, options = {}) {
203203
const { mimeTypes } = options;
204204

205205
if (mimeTypes) {
206-
const { types } = mime;
207-
208-
// mimeTypes from user provided options should take priority
209-
// over existing, known types
210-
// @ts-expect-error
211-
mime.types = { ...types, ...mimeTypes };
206+
// mrmime.lookup closes over the exported dictionary, so overrides
207+
// need to update the object in place.
208+
for (const [extension, type] of Object.entries(mimeTypes)) {
209+
mimes[extension.toLowerCase()] = type;
210+
}
212211
}
213212

214213
/**

src/middleware.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const path = require("node:path");
22

3-
const mime = require("mime-types");
4-
3+
const { lookup, mimes } = require("mrmime");
54
const onFinishedStream = require("on-finished");
65

76
const {
@@ -34,6 +33,35 @@ const ready = require("./utils/ready");
3433
/** @typedef {import("fs").ReadStream} ReadStream */
3534

3635
const BYTES_RANGE_REGEXP = /^ *bytes/i;
36+
const UTF8_CHARSET_MIME_TYPES = new Set([
37+
"application/javascript",
38+
"application/json",
39+
"application/manifest+json",
40+
]);
41+
42+
mimes.usdz = "model/vnd.usdz+zip";
43+
44+
/**
45+
* @param {string} filename filename or extension
46+
* @returns {string | undefined} content type header value
47+
*/
48+
function getContentType(filename) {
49+
const mimeType = lookup(filename);
50+
51+
if (!mimeType) {
52+
return undefined;
53+
}
54+
55+
if (mimeType.includes(";")) {
56+
return mimeType;
57+
}
58+
59+
if (mimeType.startsWith("text/") || UTF8_CHARSET_MIME_TYPES.has(mimeType)) {
60+
return `${mimeType}; charset=utf-8`;
61+
}
62+
63+
return mimeType;
64+
}
3765

3866
/**
3967
* @param {"bytes"} type type
@@ -688,7 +716,7 @@ function wrapper(context) {
688716
) {
689717
removeResponseHeader(res, "Content-Type");
690718
// content-type name (like application/javascript; charset=utf-8) or false
691-
const contentType = mime.contentType(path.extname(filename));
719+
const contentType = getContentType(path.extname(filename));
692720

693721
// Only set content-type header if media type is known
694722
// https://tools.ietf.org/html/rfc7231#section-3.1.1.5

test/middleware.test.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import finalhandler from "finalhandler";
1111
import { Hono } from "hono";
1212
import koa from "koa";
1313
import memfs, { Volume, createFsFromVolume } from "memfs";
14-
import mime from "mime-types";
14+
import { lookup, mimes } from "mrmime";
1515
import router from "router";
1616
import request from "supertest";
1717
import { Stats } from "@rspack/core";
@@ -34,6 +34,14 @@ import getCompilerHooks from "./helpers/getCompilerHooks";
3434
// Suppress unnecessary stats output
3535
rs.spyOn(globalThis.console, "log").mockImplementation();
3636

37+
const UTF8_CHARSET_MIME_TYPES = new Set([
38+
"application/javascript",
39+
"application/json",
40+
"application/manifest+json",
41+
]);
42+
43+
mimes.usdz = "model/vnd.usdz+zip";
44+
3745
async function startServer(name, app) {
3846
return new Promise((resolve, reject) => {
3947
if (name === "router") {
@@ -270,7 +278,21 @@ function get404ContentTypeHeader(name) {
270278
}
271279

272280
function getContentTypeHeader(name, ext = "js") {
273-
return mime.contentType(ext);
281+
const mimeType = lookup(ext);
282+
283+
if (!mimeType) {
284+
return undefined;
285+
}
286+
287+
if (mimeType.includes(";")) {
288+
return mimeType;
289+
}
290+
291+
if (mimeType.startsWith("text/") || UTF8_CHARSET_MIME_TYPES.has(mimeType)) {
292+
return `${mimeType}; charset=utf-8`;
293+
}
294+
295+
return mimeType;
274296
}
275297

276298
function applyTestMiddleware(name, middlewares) {

0 commit comments

Comments
 (0)