1 | <div align="center">
|
2 | <a href="https://github.com/webpack/webpack">
|
3 | <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
4 | </a>
|
5 | </div>
|
6 |
|
7 | [![npm][npm]][npm-url]
|
8 | [![node][node]][node-url]
|
9 | [![deps][deps]][deps-url]
|
10 | [![tests][tests]][tests-url]
|
11 | [![coverage][cover]][cover-url]
|
12 | [![chat][chat]][chat-url]
|
13 |
|
14 | # webpack-dev-middleware
|
15 |
|
16 | An express-style development middleware for use with [webpack](https://webpack.js.org)
|
17 | bundles and allows for serving of the files emitted from webpack.
|
18 | This should be used for **development only**.
|
19 |
|
20 | Some of the benefits of using this middleware include:
|
21 |
|
22 | - No files are written to disk, rather it handles files in memory
|
23 | - If files changed in watch mode, the middleware delays requests until compiling
|
24 | has completed.
|
25 | - Supports hot module reload (HMR).
|
26 |
|
27 | ## Getting Started
|
28 |
|
29 | First thing's first, install the module:
|
30 |
|
31 | ```console
|
32 | npm install webpack-dev-middleware --save-dev
|
33 | ```
|
34 |
|
35 | _Note: We do not recommend installing this module globally._
|
36 |
|
37 | ## Requirements
|
38 |
|
39 | `webpack-dev-middleware` requires Node v6 or higher, and must be used with a
|
40 | server that accepts express-style middleware.
|
41 |
|
42 | ## Usage
|
43 |
|
44 | ```js
|
45 | const webpack = require('webpack');
|
46 | const middleware = require('webpack-dev-middleware');
|
47 | const compiler = webpack({ .. webpack options .. });
|
48 | const express = require('express');
|
49 | const app = express();
|
50 |
|
51 | app.use(middleware(compiler, {
|
52 | // webpack-dev-middleware options
|
53 | }));
|
54 |
|
55 | app.listen(3000, () => console.log('Example app listening on port 3000!'))
|
56 | ```
|
57 |
|
58 | ## Options
|
59 |
|
60 | The middleware accepts an `options` Object. The following is a property reference
|
61 | for the Object.
|
62 |
|
63 | _Note: The `publicPath` property is required, whereas all other options are optional_
|
64 |
|
65 | ### headers
|
66 |
|
67 | Type: `Object`
|
68 | Default: `undefined`
|
69 |
|
70 | This property allows a user to pass custom HTTP headers on each request. eg.
|
71 | `{ "X-Custom-Header": "yes" }`
|
72 |
|
73 | index
|
74 |
|
75 | Type: `String`
|
76 | Default: `undefined`
|
77 |
|
78 | "index.html",
|
79 | // The index path for web server, defaults to "index.html".
|
80 | // If falsy (but not undefined), the server will not respond to requests to the root URL.
|
81 |
|
82 |
|
83 | ### lazy
|
84 |
|
85 | Type: `Boolean`
|
86 | Default: `undefined`
|
87 |
|
88 | This option instructs the module to operate in 'lazy' mode, meaning that it won't
|
89 | recompile when files change, but rather on each request.
|
90 |
|
91 | ### logger
|
92 |
|
93 | Type: `Object`
|
94 | Default: [`log`](/webpack/webpack-dev-middleware/blob/master/lib/log.js)
|
95 |
|
96 | In the rare event that a user would like to provide a custom logging interface,
|
97 | this property allows the user to assign one. The module leverages
|
98 | [`loglevel`](https://github.com/pimterry/loglevel#documentation)
|
99 | for logging management by default, and any custom logger must adhere to the same
|
100 | exports for compatibility. Specifically, all custom loggers must have the
|
101 | following exported methods at a minimum:
|
102 |
|
103 | - `log.trace`
|
104 | - `log.debug`
|
105 | - `log.info`
|
106 | - `log.warn`
|
107 | - `log.error`
|
108 |
|
109 | Please see the documentation for `loglevel` for more information.
|
110 |
|
111 | ### logLevel
|
112 |
|
113 | Type: `String`
|
114 | Default: `'info'`
|
115 |
|
116 | This property defines the level of messages that the module will log. Valid levels
|
117 | include:
|
118 |
|
119 | - `trace`
|
120 | - `debug`
|
121 | - `info`
|
122 | - `warn`
|
123 | - `error`
|
124 | - `silent`
|
125 |
|
126 | Setting a log level means that all other levels below it will be visible in the
|
127 | console. Setting `logLevel: 'silent'` will hide all console output. The module
|
128 | leverages [`loglevel`](https://github.com/pimterry/loglevel#documentation)
|
129 | for logging management, and more information can be found on its page.
|
130 |
|
131 | ## logTime
|
132 |
|
133 | Type: `Boolean`
|
134 | Default: `false`
|
135 |
|
136 | If `true` the log output of the module will be prefixed by a timestamp in the
|
137 | `HH:mm:ss` format.
|
138 |
|
139 | ### mimeTypes
|
140 |
|
141 | Type: `Object`
|
142 | Default: `null`
|
143 |
|
144 | This property allows a user to register custom mime types or extension mappings.
|
145 | eg. `{ 'text/html': [ 'phtml' ] }`. Please see the documentation for
|
146 | [`node-mime`](https://github.com/broofa/node-mime#mimedefine) for more information.
|
147 |
|
148 | ### publicPath
|
149 |
|
150 | Type: `String`
|
151 | _Required_
|
152 |
|
153 | The public path that the middleware is bound to. _Best Prectice: use the same
|
154 | `publicPath` defined in your webpack config._
|
155 |
|
156 | ### reporter
|
157 |
|
158 | Type: `Object`
|
159 | Default: `undefined`
|
160 |
|
161 | Allows users to provide a custom reporter to handle logging within the module.
|
162 | Please see the [default reporter](/webpack/webpack-dev-middleware/blob/master/lib/reporter.js)
|
163 | for an example.
|
164 |
|
165 | ### serverSideRender
|
166 |
|
167 | Type: `Boolean`
|
168 | Default: `undefined`
|
169 |
|
170 | Instructs the module to enable or disable the server-side rendering mode. Please
|
171 | see [Server-Side Rendering](#server-side-rendering) for more information.
|
172 |
|
173 | ### stats
|
174 | Type: `Object`
|
175 | Default: `{ context: process.cwd() }`
|
176 |
|
177 | Options for formatting statistics displayed during and after compile. For more
|
178 | information and property details, please see the
|
179 | [webpack documentation](https://webpack.js.org/configuration/stats/#stats).
|
180 |
|
181 | ### watchOptions
|
182 |
|
183 | Type: `Object`
|
184 | Default: `{ aggregateTimeout: 200 }``
|
185 |
|
186 | The module accepts an `Object` containing options for file watching, which is
|
187 | passed directly to the compiler provided. For more information on watch options
|
188 | please see the [webpack documentation](https://webpack.js.org/configuration/watch/#watchoptions)
|
189 |
|
190 | ## API
|
191 |
|
192 | `webpack-dev-middleware` also provides convenience methods that can be use to
|
193 | interact with the middleware at runtime:
|
194 |
|
195 | ### `close(callback)`
|
196 |
|
197 | Instructs a webpack-dev-middleware instance to stop watching for file changes.
|
198 |
|
199 | ### Parameters
|
200 |
|
201 | #### callback
|
202 |
|
203 | Type: `Function`
|
204 |
|
205 | A function executed once the middleware has stopped watching.
|
206 |
|
207 | ### `invalidate()`
|
208 |
|
209 | Instructs a webpack-dev-middleware instance to recompile the bundle.
|
210 | e.g. after a change to the configuration.
|
211 |
|
212 | ```js
|
213 | const webpack = require('webpack');
|
214 | const compiler = webpack({ ... });
|
215 | const middlware = require('webpack-dev-middleware');
|
216 | const instance = middleware(compiler);
|
217 |
|
218 | app.use(instance);
|
219 |
|
220 | setTimeout(() => {
|
221 | // After a short delay the configuration is changed and a banner plugin is added
|
222 | // to the config
|
223 | compiler.apply(new webpack.BannerPlugin('A new banner'));
|
224 |
|
225 | // Recompile the bundle with the banner plugin:
|
226 | instance.invalidate();
|
227 | }, 1000);
|
228 | ```
|
229 |
|
230 | ### `waitUntilValid(callback)`
|
231 |
|
232 | Executes a callback function when the compiler bundle is valid, typically after
|
233 | compilation.
|
234 |
|
235 | ### Parameters
|
236 |
|
237 | #### callback
|
238 |
|
239 | Type: `Function`
|
240 |
|
241 | A function executed when the bundle becomes valid. If the bundle is
|
242 | valid at the time of calling, the callback is executed immediately.
|
243 |
|
244 | ```js
|
245 | const webpack = require('webpack');
|
246 | const compiler = webpack({ ... });
|
247 | const middlware = require('webpack-dev-middleware');
|
248 | const instance = middleware(compiler);
|
249 |
|
250 | app.use(instance);
|
251 |
|
252 | instance.waitUntilValid(() => {
|
253 | console.log('Package is in a valid state');
|
254 | });
|
255 | ```
|
256 |
|
257 | ## Server-Side Rendering
|
258 |
|
259 | _Note: this feature is experimental and may be removed or changed completely in the future._
|
260 |
|
261 | In order to develop an app using server-side rendering, we need access to the
|
262 | [`stats`](https://github.com/webpack/docs/wiki/node.js-api#stats), which is
|
263 | generated with each build.
|
264 |
|
265 | With server-side rendering enabled, `webpack-dev-middleware` sets the `stat` to
|
266 | `res.locals.webpackStats` before invoking the next middleware, allowing a
|
267 | developer to render the page body and manage the response to clients.
|
268 |
|
269 | _Note: Requests for bundle files will still be handled by
|
270 | `webpack-dev-middleware` and all requests will be pending until the build
|
271 | process is finished with server-side rendering enabled._
|
272 |
|
273 | Example Implementation:
|
274 |
|
275 | ```js
|
276 | const webpack = require('webpack');
|
277 | const compiler = webpack({ ... });
|
278 | const middlware = require('webpack-dev-middleware');
|
279 |
|
280 | // This function makes server rendering of asset references consistent with different webpack chunk/entry configurations
|
281 | function normalizeAssets(assets) {
|
282 | return Array.isArray(assets) ? assets : [assets]
|
283 | }
|
284 |
|
285 | app.use(middleware(compiler, { serverSideRender: true })
|
286 |
|
287 | // The following middleware would not be invoked until the latest build is finished.
|
288 | app.use((req, res) => {
|
289 | const assetsByChunkName = res.locals.webpackStats.toJson().assetsByChunkName
|
290 |
|
291 | // then use `assetsByChunkName` for server-sider rendering
|
292 | // For example, if you have only one main chunk:
|
293 | res.send(`
|
294 | <html>
|
295 | <head>
|
296 | <title>My App</title>
|
297 | ${normalizeAssets(assetsByChunkName.main)
|
298 | .filter(path => path.endsWith('.css'))
|
299 | .map(path => `<link rel="stylesheet" href="${path}" />`)
|
300 | .join('\n')}
|
301 | </head>
|
302 | <body>
|
303 | <div id="root"></div>
|
304 | ${normalizeAssets(assetsByChunkName.main)
|
305 | .filter(path => path.endsWith('.js'))
|
306 | .map(path => `<script src="${path}"></script>`)
|
307 | .join('\n')}
|
308 | </body>
|
309 | </html>
|
310 | `)
|
311 |
|
312 | })
|
313 | ```
|
314 |
|
315 | ## Support
|
316 |
|
317 | We do our best to keep Issues in the repository focused on bugs, features, and
|
318 | needed modifications to the code for the module. Because of that, we ask users
|
319 | with general support, "how-to", or "why isn't this working" questions to try one
|
320 | of the other support channels that are available.
|
321 |
|
322 | Your first-stop-shop for support for webpack-dev-server should by the excellent
|
323 | [documentation][docs-url] for the module. If you see an opportunity for improvement
|
324 | of those docs, please head over to the [webpack.js.org repo][wjo-url] and open a
|
325 | pull request.
|
326 |
|
327 | From there, we encourage users to visit the [webpack Gitter chat][chat-url] and
|
328 | talk to the fine folks there. If your quest for answers comes up dry in chat,
|
329 | head over to [StackOverflow][stack-url] and do a quick search or open a new
|
330 | question. Remember; It's always much easier to answer questions that include your
|
331 | `webpack.config.js` and relevant files!
|
332 |
|
333 | If you're twitter-savvy you can tweet [#webpack][hash-url] with your question
|
334 | and someone should be able to reach out and lend a hand.
|
335 |
|
336 | If you have discovered a :bug:, have a feature suggestion, of would like to see
|
337 | a modification, please feel free to create an issue on Github. _Note: The issue
|
338 | template isn't optional, so please be sure not to remove it, and please fill it
|
339 | out completely._
|
340 |
|
341 | ## Contributing
|
342 |
|
343 | We welcome your contributions! Please have a read of [CONTRIBUTING.md](CONTRIBUTING.md) for more information on how to get involved.
|
344 |
|
345 | ## Maintainers
|
346 |
|
347 | <table>
|
348 | <tbody>
|
349 | <tr>
|
350 | <td align="center">
|
351 | <img src="https://avatars.githubusercontent.com/SpaceK33z?v=4&s=150">
|
352 | <br />
|
353 | <a href="https://github.com/SpaceK33z">Kees Kluskens</a>
|
354 | </td>
|
355 | <td align="center">
|
356 | <img src="https://i.imgur.com/4v6pgxh.png">
|
357 | <br />
|
358 | <a href="https://github.com/shellscape">Andrew Powell</a>
|
359 | </td>
|
360 | </tr>
|
361 | </tbody>
|
362 | </table>
|
363 |
|
364 | ## License
|
365 |
|
366 | #### [MIT](./LICENSE)
|
367 |
|
368 | [npm]: https://img.shields.io/npm/v/webpack-dev-middleware.svg
|
369 | [npm-url]: https://npmjs.com/package/webpack-dev-middleware
|
370 |
|
371 | [node]: https://img.shields.io/node/v/webpack-dev-middleware.svg
|
372 | [node-url]: https://nodejs.org
|
373 |
|
374 | [deps]: https://david-dm.org/webpack/webpack-dev-middleware.svg
|
375 | [deps-url]: https://david-dm.org/webpack/webpack-dev-middleware
|
376 |
|
377 | [tests]: http://img.shields.io/travis/webpack/webpack-dev-middleware.svg
|
378 | [tests-url]: https://travis-ci.org/webpack/webpack-dev-middleware
|
379 |
|
380 | [cover]: https://codecov.io/gh/webpack/webpack-dev-middleware/branch/master/graph/badge.svg
|
381 | [cover-url]: https://codecov.io/gh/webpack/webpack-dev-middleware
|
382 |
|
383 | [chat]: https://badges.gitter.im/webpack/webpack.svg
|
384 | [chat-url]: https://gitter.im/webpack/webpack
|
385 |
|
386 | [docs-url]: https://webpack.js.org/configuration/dev-middleware/#devmiddleware
|
387 | [hash-url]: https://twitter.com/search?q=webpack
|
388 | [middleware-url]: https://github.com/webpack/webpack-dev-middleware
|
389 | [stack-url]: https://stackoverflow.com/questions/tagged/webpack-dev-middleware
|
390 | [uglify-url]: https://github.com/webpack-contrib/uglifyjs-webpack-plugin
|
391 | [wjo-url]: https://github.com/webpack/webpack.js.org
|