tools.devServer
The config of DevServer can be modified through tools.devServer
.
Options
after
Provides the ability to execute custom middleware after all other middleware internally within the server.
export default {
tools: {
devServer: {
after: [
async (req, res, next) => {
console.log('after dev middleware');
next();
},
],
},
},
};
webpack-dev-server
uses Express as the server-side framework. Modern.js does not use any framework, and the req
and res
in the above middleware are all native Node objects. Therefore, the Express middleware used in webpack-dev-server
may not be directly usable in Modern.js.
If you want to migrate the Express middleware used in webpack-dev-server
, you can use the following method to pass the Express app as middleware:
import expressMiddleware from 'my-express-middleware';
import express from 'express';
// init Express app
const app = express();
app.use(expressMiddleware);
export default {
tools: {
devServer: {
after: [app],
},
},
};
before
Provides the ability to execute custom middleware prior to all other middleware internally within the server.
export default {
tools: {
devServer: {
before: [
async (req, res, next) => {
console.log('before dev middleware');
next();
},
],
},
},
};
client
WARNING
Deprecated: This configuration is deprecated, please use dev.client instead.
{
/** Specify a protocol to use */
protocol?: string;
/** The path which the middleware is serving the event stream on */
path?: string;
/** Specify a port number to listen for requests on */
port?: string;
/** Specify a host to use */
host?: string;
}
const defaultConfig = {
path: '/webpack-hmr',
// By default it is set to the port number of the dev server
port: '',
// By default it is set to "location.hostname"
host: '',
// By default it is set to "location.protocol === 'https:' ? 'wss' : 'ws'""
protocol: '',
};
The config of HMR client, which are usually used to set the WebSocket URL of HMR.
compress
- Type:
boolean
- Default:
true
Whether to enable gzip compression for served static assets.
If you want to disable the gzip compression, you can set compress
to false
:
export default {
tools: {
devServer: {
compress: false,
},
},
};
devMiddleware
{
writeToDisk: boolean | ((filename: string) => boolean);
}
{
writeToDisk: (file: string) => !file.includes('.hot-update.'),
}
The config of devMiddleware. Current options is the subset of webpack-dev-middleware.
- Type:
Record<string, string>
- Default:
undefined
Adds headers to all responses.
export default {
tools: {
devServer: {
headers: {
'X-Custom-Foo': 'bar',
},
},
},
};
historyApiFallback
- Type:
boolean | ConnectHistoryApiFallbackOptions
- Default:
false
The index.html page will likely have to be served in place of any 404 responses. Enable devServer.historyApiFallback
by setting it to true
:
export default {
tools: {
devServer: {
historyApiFallback: true,
},
},
};
For more options and information, see the connect-history-api-fallback documentation.
hot
- Type:
boolean
- Default:
true
Enable Hot Module Replacement feature.
https
- Type:
boolean | { key: string; cert: string }
- Default:
false
By default, DevServer will be served over HTTP. It can optionally be served over HTTPS by setting devServer.https
to true
, and will disable the HTTP server.
You can also manually pass in the certificate and corresponding private key required by the HTTPS server:
export default {
tools: {
devServer: {
https: {
key: fs.readFileSync('certificates/private.pem'),
cert: fs.readFileSync('certificates/public.pem'),
},
},
},
};
liveReload
- Type:
boolean
- Default:
true
By default, the DevServer will reload/refresh the page when file changes are detected (devServer.hot
option must be disabled in order for liveReload to take effect). Disable devServer.liveReload
by setting it to false
.
setupMiddlewares
Array<
(
middlewares: {
unshift: (...handlers: RequestHandler[]) => void;
push: (...handlers: RequestHandler[]) => void;
},
server: {
sockWrite: (
type: string,
data?: string | boolean | Record<string, any>,
) => void;
},
) => void
>;
Provides the ability to execute a custom function and apply custom middlewares.
The order among several different types of middleware is: devServer.before
=> unshift
=> internal middlewares => push
=> devServer.after
.
export default {
tools: {
devServer: {
setupMiddlewares: [
(middlewares, server) => {
middlewares.unshift((req, res, next) => {
next();
});
middlewares.push((req, res, next) => {
next();
});
},
],
},
},
};
It is possible to use some server api to meet special scenario requirements:
- sockWrite. Allow send some message to hmr client, and then the hmr client will take different actions depending on the message type. If you send a "content changed" message, the page will reload.
export default {
tools: {
devServer: {
setupMiddlewares: [
(middlewares, server) => {
// add custom watch & trigger page reload when change
watcher.on('change', changed => {
server.sockWrite('content-changed');
});
},
],
},
},
};
proxy
- Type:
Record<string, string> | Record<string, ProxyDetail>
- Default:
undefined
Proxying some URLs.
export default {
tools: {
devServer: {
proxy: {
'/api': 'http://localhost:3000',
},
},
},
};
A request to /api/users will now proxy the request to http://localhost:3000/api/users.
If you don't want /api to be passed along, we need to rewrite the path:
export default {
tools: {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
},
},
},
},
};
The DevServer Proxy makes use of the http-proxy-middleware package. Check out its documentation for more advanced usages.
The full type definition of DevServer Proxy is:
import type { Options as HttpProxyOptions } from 'http-proxy-middleware';
type Filter = string | string[] | ((pathname: string, req: Request) => boolean);
type ProxyDetail = HttpProxyOptions & {
bypass?: (
req: IncomingMessage,
res: ServerResponse,
proxyOptions: ProxyOptions,
) => string | undefined | null | false;
context?: Filter;
};
type ProxyOptions =
| Record<string, string>
| Record<string, ProxyDetail>
| ProxyDetail[]
| ProxyDetail;
In addition to the http-proxy-middleware option, we also support the bypass and context configuration:
- bypass: bypass the proxy based on the return value of a function.
- Return
null
or undefined
to continue processing the request with proxy.
- Return
false
to produce a 404 error for the request.
- Return a path to serve from, instead of continuing to proxy the request.
- context: If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a context property.
// custom bypass
export default {
tools: {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
bypass: function (req, res, proxyOptions) {
if (req.headers.accept.indexOf('html') !== -1) {
console.log('Skipping proxy for browser request.');
return '/index.html';
}
},
},
},
},
},
};
// proxy multiple
export default {
tools: {
devServer: {
proxy: [
{
context: ['/auth', '/api'],
target: 'http://localhost:3000',
},
],
},
},
};
watch
- Type:
boolean
- Default:
true
Whether to watch files change in directories such as mock/
, server/
, api/
.