webpack-dev-server
官方文档:http://webpack.github.io/docs/webpack-dev-server.html#webpack-dev-server-cli
课件:http://www.68kejian.com/page/study/course/76/447
注意:你启动webpack-dev-server后,你在目标文件夹中是看不到编译后的文件的,实时编译后的文件都保存到了内存当中。因此很多同学使用webpack-dev-server进行开发的时候都看不到编译后的文件
启动
启动 webpack-dev-server
有2种方式:
cmd line
Node.js API
1.webpack-dev-server是一个轻量级的服务器,修改文件源码后,自动刷新页面将修改同步到页面上
2.安装webpack-dev-server:
全局安装:npm install webpack-dev-server -g
在项目中安装并将依赖写在package.json文件中:npm install webpack-dev-server --save-dev
3.使用命令webpack-dev-server --hot --inline完成自动刷新
4.默认的端口号是8080,如果需要8080端口被占用,就需要改端口,webpack-dev-server --port 3000(将端口号改为3000)
5.安装webpack-dev-server后就可以在命令行中输入webpack-dev-server开启服务,然后在浏览器地址栏中
输入localhost:端口号,就可以在浏览器中打开项目根目录的index.html文件,如果项目根目录中没有index.html
文件,就会在浏览器中列出项目根目录中的所有的文件夹。
6.第五条只是启动服务并不能自动刷新,要自动刷新需要用到webpack-dev-server --hot --inline
7.当使用webpack-dev-server --hot --inline命令时,在每次修改文件,是将文件打包
保存在内存中并没有写在磁盘里(默认是根据webpack.config.js打包文件,通过--config xxxx.js修改),这种打包得到的文件
和项目根目录中的index.html位于同一级(但是你看不到,因为
它在内存中并没有在磁盘里)。使用webpack命令将打包后的文件保存在磁盘中
例如在index.html文件中引入通过webpack-dev-server --hot --inline打包的build.js
<script src="build.js"></script>
在index.html文件中引入通过webpack命令打包的build.js
<script src="./build/build.js"></script>
8.每一次都敲一长串命令太麻烦,在项目根目录的package.json文件的scripts配置中添加配置,如
"build":"webpack-dev-server --hot --inline",然后在命令行中输入 npm run build就能
代替输入一长串命令(webpack-dev-server --hot --inline),运行webpack-dev-server --hot --inline默认是找
webpack.config.js,通过--config命令可以修改为另一个配置文件。例如:webpack-dev-server --hot --inline --config '
webpack.es6.config.js'
9.配置根目录
(1)当在命令行中输入webpack-dev-server --hot --inline,再在浏览器中输入localhost:端口号,浏览器会在项目的
根目录中去查找内容,通过--content-base可以配置根目录。
如webpack-dev-server --hot --inline --content-base './build/',在build文件夹中去加载index.html,如果没有
index.html文件,将会在浏览器中显示所有build目录下的文件和文件夹
webpack-dev-server中的配置选项
var WebpackDevServer = require("webpack-dev-server");
var webpack = require("webpack");
var compiler = webpack({
// configuration
});
var server = new WebpackDevServer(compiler, {
// webpack-dev-server options
contentBase: "/path/to/directory",
// Can also be an array, or: contentBase: "http://localhost/",
hot: true,
// Enable special support for Hot Module Replacement
// Page is no longer updated, but a "webpackHotUpdate" message is send to the content
// Use "webpack/hot/dev-server" as additional module in your entry point
// Note: this does _not_ add the `HotModuleReplacementPlugin` like the CLI option does.
// Set this as true if you want to access dev server from arbitrary url.
// This is handy if you are using a html5 router.
historyApiFallback: false,
// Set this if you want to enable gzip compression for assets
compress: true,
// Set this if you want webpack-dev-server to delegate a single path to an arbitrary server.
// Use "**" to proxy all paths to the specified server.
// This is useful if you want to get rid of 'http://localhost:8080/' in script[src],
// and has many other use cases (see https://github.com/webpack/webpack-dev-server/pull/127 ).
proxy: {
"**": "http://localhost:9090"
},
setup: function(app) {
// Here you can access the Express app object and add your own custom middleware to it.
// For example, to define custom handlers for some paths:
// app.get('/some/path', function(req, res) {
// res.json({ custom: 'response' });
// });
},
// pass [static options](http://expressjs.com/en/4x/api.html#express.static) to inner express server
staticOptions: {
},
// webpack-dev-middleware options
quiet: false,
noInfo: false,
lazy: true,
filename: "bundle.js",
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
// It's a required option.
publicPath: "/assets/",
headers: { "X-Custom-Header": "yes" },
stats: { colors: true }
});
server.listen(8080, "localhost", function() {});
// server.close();
content-base
设定 webpack-dev-server
伺服的 directory
。如果不进行设定的话,默认是在当前目录下。
webpack-dev-server --content-base ./dist
这个时候还要注意的一点就是在 webpack.config.js
文件里面,如果配置了 output
的 publicPath
这个字段的值的话,在 index.html
文件里面也应该做出调整。因为 webpack-dev-server
伺服的文件是相对 publicPath
这个路径的 。因此,如果你的 webpack.config.js
配置成这样的:
module.exports = {
entry: './src/js/index.js',
output: {
path: './dist/js',
filename: 'bundle.js',
publicPath: '/assets/'
}
}
那么,在 index.html
文件当中引入的路径也发生相应的变化:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<script src="assets/bundle.js"></script>
</body>
</html>
如果在 webpack.config.js
里面没有配置 output
的 publicPath
的话,那么 index.html
最后引入的文件 js文件
路径应该是下面这样的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
Automatic Refresh
webpack-dev-server
支持2种自动刷新的方式:
-
Iframe mode
-
inline mode
这2种模式配置的方式和访问的路径稍微有点区别,最主要的区别还是 Iframe mode
是在网页中嵌入了一个 iframe
,将我们自己的应用注入到这个 iframe
当中去,因此每次你修改的文件后,都是这个 iframe
进行了 reload
。
通过查看 webpack-dev-server
的源码, lib
路径下的 Server.js
文件,第38-48行,分别新建几个流,这几个流保存了 client
文件夹下的相关文件:
// Prepare live html page
var livePage = this.livePage = new StreamCache();
fs.createReadStream(path.join(__dirname, "..", "client", "live.html")).pipe(livePage);
// Prepare the live js file
var liveJs = new StreamCache();
fs.createReadStream(path.join(__dirname, "..", "client", "live.bundle.js")).pipe(liveJs);
// Prepare the inlined js file
var inlinedJs = new StreamCache();
fs.createReadStream(path.join(__dirname, "..", "client", "index.bundle.js")).pipe(inlinedJs);
// Init express server
var app = this.app = new express();
// middleware for serving webpack bundle
this.middleware = webpackDevMiddleware(compiler, options);
app.get("/__webpack_dev_server__/live.bundle.js", function(req, res) {
res.setHeader("Content-Type", "application/javascript");
liveJs.pipe(res);
});
app.get("/webpack-dev-server.js", function(req, res) {
res.setHeader("Content-Type", "application/javascript");
inlinedJs.pipe(res);
});
app.get("/webpack-dev-server/*", function(req, res) {
res.setHeader("Content-Type", "text/html");
this.livePage.pipe(res);
}.bind(this));
当使用 Iframe mode
时,请求 /webpack-dev-server/index.html
路径时,会返回 client/index.html
文件,这个文件的内容就是:
<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta charset="utf-8"/><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/><script type="text/javascript" charset="utf-8" src="/__webpack_dev_server__/live.bundle.js"></script></head><body></body></html>
这个页面会请求 live.bundle.js
,其中里面会新建一个 Iframe
,你的应用就被注入到了这个 Iframe
当中。同时 live.bundle.js
中含有 socket.io
的 client
代码,这样它就能和 webpack-dev-server
建立的 http server
进行 websocket
通讯了。并根据返回的信息完成相应的动作。
而 Inline-mode
,是 webpack-dev-server
会在你的 webpack.config.js
的入口配置文件中再添加一个入口,
module.exports = {
entry: {
app: [
'webpack-dev-server/client?http://localhost:8080/',
'./src/js/index.js'
]
},
output: {
path: './dist/js',
filename: 'bundle.js'
}
}
这样就完成了将 inlinedJS
打包进 bundle.js
里的功能,同时 inlinedJS
里面也包含了 socket.io
的 client
代码,可以和 webpack-dev-server
进行 websocket
通讯。
当然你也可以直接在你 index.html
引入这部分代码:
<script src="http://localhost:8080/webpack-dev-server.js"></script>
不过 Iframe mode
和 Inline mode
最后达到的效果都是一样的,都是监听文件的变化,然后再将编译后的文件推送到前端,完成页面的 reload
的。
Iframe mode
Iframe mode
下 cmd line
不需要添加其他的内容,浏览器访问的路径是:
localhost:8080/webpack-dev-server/index.html。
这个时候这个页面的 header部分
会出现整个 reload消息
的状态。当时改变源文件的时候,即可以完成自动编译打包,页面自动刷新的功能。
Inline mode
使用 inline mode
的时候, cmd line
需要写成:
webpack-dev-server --inline --content-base ./dist
这个时候访问的路径是:
localhost:8080/index.html
也能完成自动编译打包,页面自动刷新的功能。但是没有的 header
部分的reload
消息的显示,不过在控制台中会显示 reload
的状态。
Hot Module Replacement
开启 Hot Module Replacemen
t功能,在 cmd line
里面添加 --hot
webpack-dev-server --hot --inline --content-base ./dist
--content-base //设定webpack-dev-server的director根目录。如果不进行设定的话,默认是在当前目录下。
--quiet: //控制台中不输出打包的信息,开发中一般设置为false,进行 打印,这样查看错误比较方面
--no-info: // 不显示任何信息
--colors: //对信息进行颜色输出
--no-colors: //对信息不进行颜色输出
--compress: //开启gzip压缩
--host <hostname/ip>: //设置ip
--port <number>: //设置端口号,默认是:8080
--inline: //webpack-dev-server会在你的webpack.config.js的入口配置文件中再添加一个入口,
--hot: //开发热替换
--open: //启动命令,自动打开浏览器
--history-api-fallback: //如果设为browserHistory,
这种情况需要对服务器改造。否则用户直接向服务器请求某个子路由,会显示网页找不到的404错误。配置上这个参数即可解决
这是我的 package.json
的文件:
{
"name": "reptile",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
//--devtool eval - 为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号
//https://sanwen.net/a/ltjldpo.html [webpack]devtool里的7种SourceMap模式是什么鬼?
"dev": "webpack-dev-server --devtool eval-source-map --progress --colors --hot --inline --content-base ./dist",
"build": "webpack --progress --colors"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.13.2",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.13.2",
"babel-preset-react": "^6.11.1",
"css-loader": "^0.23.1",
"react": "^15.3.1",
"react-dom": "^15.3.1",
"style-loader": "^0.13.1",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.14.1"
}
}
首先命令行:输入 npm install
所有依赖。然后输入 npm run dev
。在浏览器中打开localhost:8080/index.html,然后就可以愉快的开发咯。
如果对 web-dev-server
还有其他问题的话,请留言告知。