Socket
Socket
Sign inDemoInstall

webpack-dev-middleware

Package Overview
Dependencies
82
Maintainers
4
Versions
113
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.0.2 to 6.1.0

20

dist/index.js

@@ -22,2 +22,3 @@ "use strict";

/** @typedef {import("webpack").MultiStats} MultiStats */
/** @typedef {import("fs").ReadStream} ReadStream */

@@ -62,4 +63,21 @@ /**

/**
* @typedef {Object} ResponseData
* @property {string | Buffer | ReadStream} data
* @property {number} byteLength
*/
/**
* @template {IncomingMessage} RequestInternal
* @template {ServerResponse} ResponseInternal
* @callback ModifyResponseData
* @param {RequestInternal} req
* @param {ResponseInternal} res
* @param {string | Buffer | ReadStream} data
* @param {number} byteLength
* @return {ResponseData}
*/
/**
* @template {IncomingMessage} RequestInternal
* @template {ServerResponse} ResponseInternal
* @typedef {Object} Context

@@ -87,2 +105,3 @@ * @property {boolean} state

* @property {{[key: string]: string}} [mimeTypes]
* @property {string | undefined} [mimeTypeDefault]
* @property {boolean | ((targetPath: string) => boolean)} [writeToDisk]

@@ -96,2 +115,3 @@ * @property {string} [methods]

* @property {boolean | string} [index]
* @property {ModifyResponseData<RequestInternal, ResponseInternal>} [modifyResponseData]
*/

@@ -98,0 +118,0 @@

35

dist/middleware.js

@@ -5,3 +5,2 @@ "use strict";

const mime = require("mime-types");
const parseRange = require("range-parser");
const getFilenameFromUrl = require("./utils/getFilenameFromUrl");

@@ -121,2 +120,4 @@ const {

setHeaderForResponse(res, "Content-Type", contentType);
} else if (context.options.mimeTypeDefault) {
setHeaderForResponse(res, "Content-Type", context.options.mimeTypeDefault);
}

@@ -141,3 +142,5 @@ }

});
const parsedRanges = parseRange(size, rangeHeader, {
// eslint-disable-next-line global-require
const parsedRanges = require("range-parser")(size, rangeHeader, {
combine: true

@@ -155,5 +158,13 @@ });

setHeaderForResponse(res, "Content-Type", "text/html; charset=utf-8");
const document = createHtmlDocument(416, `Error: ${message}`);
const byteLength = Buffer.byteLength(document);
/** @type {string | Buffer | import("fs").ReadStream} */
let document = createHtmlDocument(416, `Error: ${message}`);
let byteLength = Buffer.byteLength(document);
setHeaderForResponse(res, "Content-Length", Buffer.byteLength(document));
if (context.options.modifyResponseData) {
({
data: document,
byteLength
} = context.options.modifyResponseData(req, res, document, byteLength));
}
send(req, res, document, byteLength);

@@ -177,7 +188,7 @@ return;

const isFsSupportsStream = typeof context.outputFileSystem.createReadStream === "function";
let bufferOtStream;
let bufferOrStream;
let byteLength;
try {
if (typeof start !== "undefined" && typeof end !== "undefined" && isFsSupportsStream) {
bufferOtStream = /** @type {import("fs").createReadStream} */
bufferOrStream = /** @type {import("fs").createReadStream} */
context.outputFileSystem.createReadStream(filename, {

@@ -189,6 +200,6 @@ start,

} else {
bufferOtStream = /** @type {import("fs").readFileSync} */context.outputFileSystem.readFileSync(filename);
bufferOrStream = /** @type {import("fs").readFileSync} */context.outputFileSystem.readFileSync(filename);
({
byteLength
} = bufferOtStream);
} = bufferOrStream);
}

@@ -199,3 +210,9 @@ } catch (_ignoreError) {

}
send(req, res, bufferOtStream, byteLength);
if (context.options.modifyResponseData) {
({
data: bufferOrStream,
byteLength
} = context.options.modifyResponseData(req, res, bufferOrStream, byteLength));
}
send(req, res, bufferOrStream, byteLength);
}

@@ -202,0 +219,0 @@ };

@@ -9,2 +9,7 @@ {

},
"mimeTypeDefault": {
"description": "Allows a user to register a default mime type when we can't determine the content type.",
"link": "https://github.com/webpack/webpack-dev-middleware#mimetypedefault",
"type": "string"
},
"writeToDisk": {

@@ -123,2 +128,7 @@ "description": "Allows to write generated files on disk.",

]
},
"modifyResponseData": {
"description": "Allows to set up a callback to change the response data.",
"link": "https://github.com/webpack/webpack-dev-middleware#modifyresponsedata",
"instanceof": "Function"
}

@@ -125,0 +135,0 @@ },

"use strict";
const {
isColorSupported
} = require("colorette");
/** @typedef {import("webpack").Configuration} Configuration */

@@ -119,3 +115,5 @@ /** @typedef {import("webpack").Compiler} Compiler */

// eslint-disable-next-line no-param-reassign
childStatsOptions.colors = isColorSupported;
childStatsOptions.colors =
// eslint-disable-next-line global-require
require("colorette").isColorSupported;
}

@@ -128,3 +126,4 @@ return childStatsOptions;

if (typeof statsOptions.colors === "undefined") {
statsOptions.colors = isColorSupported;
// eslint-disable-next-line global-require
statsOptions.colors = require("colorette").isColorSupported;
}

@@ -131,0 +130,0 @@ }

@@ -21,4 +21,23 @@ "use strict";

outputFileSystem = outputFileSystemFromOptions;
}
// Don't use `memfs` when developer wants to write everything to a disk, because it doesn't make sense.
else if (context.options.writeToDisk !== true) {
outputFileSystem = memfs.createFsFromVolume(new memfs.Volume());
} else {
outputFileSystem = memfs.createFsFromVolume(new memfs.Volume());
const isMultiCompiler = /** @type {MultiCompiler} */
context.compiler.compilers;
if (isMultiCompiler) {
// Prefer compiler with `devServer` option or fallback on the first
// TODO we need to support webpack-dev-server as a plugin or revisit it
const compiler = /** @type {MultiCompiler} */
context.compiler.compilers.filter(item => Object.prototype.hasOwnProperty.call(item.options, "devServer"));
({
outputFileSystem
} = compiler[0] || /** @type {MultiCompiler} */
context.compiler.compilers[0]);
} else {
({
outputFileSystem
} = context.compiler);
}
}

@@ -25,0 +44,0 @@ const compilers = /** @type {MultiCompiler} */

@@ -24,7 +24,3 @@ "use strict";

for (const compiler of compilers) {
compiler.hooks.emit.tap("DevMiddleware",
/**
* @param {Compilation} compilation
*/
compilation => {
compiler.hooks.emit.tap("DevMiddleware", () => {
// @ts-ignore

@@ -35,32 +31,7 @@ if (compiler.hasWebpackDevMiddlewareAssetEmittedCallback) {

compiler.hooks.assetEmitted.tapAsync("DevMiddleware", (file, info, callback) => {
/**
* @type {string}
*/
let targetPath;
/**
* @type {Buffer}
*/
let content;
// webpack@5
if (info.compilation) {
({
targetPath,
content
} = info);
} else {
let targetFile = file;
const queryStringIdx = targetFile.indexOf("?");
if (queryStringIdx >= 0) {
targetFile = targetFile.slice(0, queryStringIdx);
}
let {
outputPath
} = compiler;
outputPath = compilation.getPath(outputPath, {});
// @ts-ignore
content = info;
targetPath = path.join(outputPath, targetFile);
}
const {
targetPath,
content
} = info;
const {
writeToDisk: filter

@@ -67,0 +38,0 @@ } = context.options;

{
"name": "webpack-dev-middleware",
"version": "6.0.2",
"version": "6.1.0",
"description": "A development middleware for webpack",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -63,13 +63,15 @@ <div align="center">

| Name | Type | Default | Description |
| :-----------------------------------------: | :-----------------------: | :-------------------------------------------: | :------------------------------------------------------------------------------------------------------------------- |
| **[`methods`](#methods)** | `Array` | `[ 'GET', 'HEAD' ]` | Allows to pass the list of HTTP request methods accepted by the middleware |
| **[`headers`](#headers)** | `Array\|Object\|Function` | `undefined` | Allows to pass custom HTTP headers on each request. |
| **[`index`](#index)** | `Boolean\|String` | `index.html` | If `false` (but not `undefined`), the server will not respond to requests to the root URL. |
| **[`mimeTypes`](#mimetypes)** | `Object` | `undefined` | Allows to register custom mime types or extension mappings. |
| **[`publicPath`](#publicpath)** | `String` | `output.publicPath` (from a configuration) | The public path that the middleware is bound to. |
| **[`stats`](#stats)** | `Boolean\|String\|Object` | `stats` (from a configuration) | Stats options object or preset name. |
| **[`serverSideRender`](#serversiderender)** | `Boolean` | `undefined` | Instructs the module to enable or disable the server-side rendering mode. |
| **[`writeToDisk`](#writetodisk)** | `Boolean\|Function` | `false` | Instructs the module to write files to the configured location on disk as specified in your `webpack` configuration. |
| **[`outputFileSystem`](#outputfilesystem)** | `Object` | [`memfs`](https://github.com/streamich/memfs) | Set the default file system which will be used by webpack as primary destination of generated files. |
| Name | Type | Default | Description |
| :---------------------------------------------: | :-----------------------: | :-------------------------------------------: | :------------------------------------------------------------------------------------------------------------------- |
| **[`methods`](#methods)** | `Array` | `[ 'GET', 'HEAD' ]` | Allows to pass the list of HTTP request methods accepted by the middleware |
| **[`headers`](#headers)** | `Array\|Object\|Function` | `undefined` | Allows to pass custom HTTP headers on each request. |
| **[`index`](#index)** | `Boolean\|String` | `index.html` | If `false` (but not `undefined`), the server will not respond to requests to the root URL. |
| **[`mimeTypes`](#mimetypes)** | `Object` | `undefined` | Allows to register custom mime types or extension mappings. |
| **[`mimeTypeDefault`](#mimetypedefault)** | `String` | `undefined` | Allows to register a default mime type when we can't determine the content type. |
| **[`publicPath`](#publicpath)** | `String` | `output.publicPath` (from a configuration) | The public path that the middleware is bound to. |
| **[`stats`](#stats)** | `Boolean\|String\|Object` | `stats` (from a configuration) | Stats options object or preset name. |
| **[`serverSideRender`](#serversiderender)** | `Boolean` | `undefined` | Instructs the module to enable or disable the server-side rendering mode. |
| **[`writeToDisk`](#writetodisk)** | `Boolean\|Function` | `false` | Instructs the module to write files to the configured location on disk as specified in your `webpack` configuration. |
| **[`outputFileSystem`](#outputfilesystem)** | `Object` | [`memfs`](https://github.com/streamich/memfs) | Set the default file system which will be used by webpack as primary destination of generated files. |
| **[`modifyResponseData`](#modifyresponsedata)** | `Function` | `undefined` | Allows to set up a callback to change the response data. |

@@ -122,10 +124,9 @@ The middleware accepts an `options` Object. The following is a property reference for the Object.

key: "X-custom-header",
value: "foo"
value: "foo",
},
{
key: "Y-custom-header",
value: "bar"
}
]
},
value: "bar",
},
],
});

@@ -141,10 +142,9 @@ ```

key: "X-custom-header",
value: "foo"
value: "foo",
},
{
key: "Y-custom-header",
value: "bar"
}
]
},
value: "bar",
},
],
});

@@ -170,2 +170,9 @@ ```

### mimeTypeDefault
Type: `String`
Default: `undefined`
This property allows a user to register a default mime type when we can't determine the content type.
### publicPath

@@ -249,2 +256,24 @@

### modifyResponseData
Allows to set up a callback to change the response data.
```js
const webpack = require("webpack");
const configuration = {
/* Webpack configuration */
};
const compiler = webpack(configuration);
middleware(compiler, {
// Note - if you send the `Range` header you will have `ReadStream`
// Also `data` can be `string` or `Buffer`
modifyResponseData: (req, res, data, byteLength) => {
// Your logic
// Don't use `res.end()` or `res.send()` here
return { data, byteLength };
},
});
```
## API

@@ -388,12 +417,31 @@

## Known Issues
## FAQ
### Multiple Successive Builds
### Avoid blocking requests to non-webpack resources.
Watching will frequently cause multiple compilations
as the bundle changes during compilation. This is due in part to cross-platform
differences in file watchers, so that webpack doesn't loose file changes when
watched files change rapidly. If you run into this situation, please make use of
the [`TimeFixPlugin`](https://github.com/egoist/time-fix-plugin).
Since `output.publicPath` and `output.filename`/`output.chunkFilename` can be dynamic, it's not possible to know which files are webpack bundles (and they public paths) and which are not, so we can't avoid blocking requests.
But there is a solution to avoid it - mount the middleware to a non-root route, for example:
```js
const webpack = require("webpack");
const middleware = require("webpack-dev-middleware");
const compiler = webpack({
// webpack options
});
const express = require("express");
const app = express();
// Mounting the middleware to the non-root route allows avoids this.
// Note - check your public path, if you want to handle `/dist/`, you need to setup `output.publicPath` to `/` value.
app.use(
"/dist/",
middleware(compiler, {
// webpack-dev-middleware options
})
);
app.listen(3000, () => console.log("Example app listening on port 3000!"));
```
## Server-Side Rendering

@@ -400,0 +448,0 @@

@@ -10,2 +10,3 @@ /// <reference types="node" />

/** @typedef {import("webpack").MultiStats} MultiStats */
/** @typedef {import("fs").ReadStream} ReadStream */
/**

@@ -40,4 +41,19 @@ * @typedef {Object} ExtendedServerResponse

/**
* @typedef {Object} ResponseData
* @property {string | Buffer | ReadStream} data
* @property {number} byteLength
*/
/**
* @template {IncomingMessage} RequestInternal
* @template {ServerResponse} ResponseInternal
* @callback ModifyResponseData
* @param {RequestInternal} req
* @param {ResponseInternal} res
* @param {string | Buffer | ReadStream} data
* @param {number} byteLength
* @return {ResponseData}
*/
/**
* @template {IncomingMessage} RequestInternal
* @template {ServerResponse} ResponseInternal
* @typedef {Object} Context

@@ -63,2 +79,3 @@ * @property {boolean} state

* @property {{[key: string]: string}} [mimeTypes]
* @property {string | undefined} [mimeTypeDefault]
* @property {boolean | ((targetPath: string) => boolean)} [writeToDisk]

@@ -72,2 +89,3 @@ * @property {string} [methods]

* @property {boolean | string} [index]
* @property {ModifyResponseData<RequestInternal, ResponseInternal>} [modifyResponseData]
*/

@@ -137,2 +155,3 @@ /**

MultiStats,
ReadStream,
ExtendedServerResponse,

@@ -148,2 +167,4 @@ IncomingMessage,

Callback,
ResponseData,
ModifyResponseData,
Context,

@@ -173,2 +194,3 @@ Headers,

| undefined;
mimeTypeDefault?: string | undefined;
writeToDisk?: boolean | ((targetPath: string) => boolean) | undefined;

@@ -182,2 +204,5 @@ methods?: string | undefined;

index?: string | boolean | undefined;
modifyResponseData?:
| ModifyResponseData<RequestInternal, ResponseInternal>
| undefined;
};

@@ -193,2 +218,3 @@ type API<

type MultiStats = import("webpack").MultiStats;
type ReadStream = import("fs").ReadStream;
type ExtendedServerResponse = {

@@ -222,2 +248,15 @@ locals?:

) => any;
type ResponseData = {
data: string | Buffer | ReadStream;
byteLength: number;
};
type ModifyResponseData<
RequestInternal extends import("http").IncomingMessage,
ResponseInternal extends ServerResponse
> = (
req: RequestInternal,
res: ResponseInternal,
data: string | Buffer | ReadStream,
byteLength: number
) => ResponseData;
type Context<

@@ -224,0 +263,0 @@ RequestInternal extends import("http").IncomingMessage,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc