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 还有其他问题的话,请留言告知。

 
posted @ 2017-06-14 21:58  little_ab  阅读(706)  评论(0编辑  收藏  举报