webpack-dev-server 其实并不难

7,962 阅读4分钟

原文链接

概述

我们都知道webpack是一个构建工具,但是在开发测试过程中,我们会经常修改代码后,然后频繁刷新页面查看效果,可惜我们就是厌旧重复工作的物种。

刚好webpack这个工具,提供了另外一个工具——webpack-dev-server,它可以帮我们从中解脱。

初试——监听入口的JS文件

我们可以监听入口文件和其它被它引用(导入)的文件,并在文件更新的时候,通知浏览器刷新网页。

使用webpack-dev-server的方式很简单:

  1. 安装:npm install --save-dev webpack-dev-server
  2. 然后设置服务器的根目录,默认为项目的根目录:
devServer: {
  contentBase: './dist',
}
  1. 然后使用指令webpack-dev-server --open就可以了。也可以把这个指令放在package.js文件里的scripts字段里。

基本原理

其实就是借助Express开启一个服务器,然后设置两个路由出口:

  1. 静态资源出口:可以通过devServer的字段contentBase设置静态资源目录
  2. webpack output的出口:默认是/,可以通过devServer的字段publicPath设置

所以,我可以看出,webpack output其实就是Express的一个router对象,webpack根据入口文件观察相关的文件,并在它们发生变化的时候,重新编译打包,并输出到router对象上,这样我们就可以访问该router拿到最新的资源,不过这个资源是放在内存上的,并不是文件系统上。

网页和webpack-dev-server是通过websocket协议互联的。当监听到文件变化的时候,会通过websocket通知网页调用reload接口刷新页面。

晋级——监听静态HTML文件

监听静态文件的变化并更新。

步骤:

  1. 安装html-webpack-plugin:npm i -D html-webpack-plugin
  2. 安装raw-loader:npm i -D raw-loader
  3. 在配置文件里配置plugin和loader:
module.exports = {
  mode: 'development',
  entry: './index.js',
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      template: "./dist/index.html" // 指定HTML模板的路径
    })
  ],
  module: {
    rules: [
      {
        test: /\.html$/,
        use: 'raw-loader'
      }
    ]
  }
}
  1. 然后在入口文件index.js里引用这个HTML模板:require('./dist/index.html')
  2. 开启服务:webpack-dev-server,更新这个index.html就可以看到刷新了

目前为止,监听文件变更后,都是通过通知浏览器刷新的方式重新访问服务器获取新的资源。

缺陷: 每个静态的HTML文件都需要在配置文件里配置一个HtmlWebpackPlugin

使用gulp监听静态文件

假如我们只想简单监听静态文件变更,然后让浏览器刷新的话,使用gulp也是不错的选择。

  1. 安装必要插件:npm i -D gulp browser-sync run-sequence
  2. 然后在gulpfile.js里指定监听文件:
var gulp = require('gulp'),
  browserSync = require('browser-sync'),
  runSequence = require('run-sequence');

gulp.task('browserSync', function () {
  browserSync.init({
    server: {
      baseDir: './dist' // 指定服务器的根目录,默认为项目的根目录
    }
  })
});

gulp.task('watch', ['browserSync'], function () {
  gulp.watch('./static/**/*.css', browserSync.reload); // 指定监听css文件
  gulp.watch('./static/**/*.js', browserSync.reload); // 指定监听js文件
  gulp.watch('./dist/*.html', browserSync.reload); // 指定监听html文件
});

gulp.task('default', function (callback) {
  runSequence(['browserSync', 'watch'], callback);
});

说明一下上面的主要两个字段:server.baseDir用于指定项目的根目录,gulp.watch()的第一个参数指的是监听文件路径,使用的时候需要根据自己的情况来改变。

  1. 最后执行gulp便可。如果终端提示找不到指令的话,可以通过安装全局的gulp,或者加个前缀.\node_modules\.bin\gulp,或者在package.js里添加一条脚本"gulp": "gulp"然后使用指令npm run gulp

高级——模块热替换

热替换功能其实也没有那么神奇。

用一句话描述就是,通过webpack提供的API监听一个文件,并替换已经存在的模块——这需要开发者自己提供替换的逻辑。

步骤:

  1. 开启热替换功能:devServer: true
  2. 注册两个插件:new webpack.NamedModulesPlugin()new webpack.HotModuleReplacementPlugin()
  3. 在需要监听的文件里,用逻辑设置需要热替换的条件,并提供热替换的逻辑。

代理功能

如果你有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用。

比如在配置文件里设置:

proxy: {
  "/api": "http://localhost:3000"
}

请求到 /api/users 现在会被代理到请求 http://localhost:3000/api/users

对于多个代理接口:

proxy: [{
  context: ["/auth", "/api"],
  target: "http://localhost:3000",
}]

常用配置

devServer.compress,启用gzip压缩。
devServer.contentBase,告诉服务器从哪里提供内容。只有在你想要提供静态文件时才需要。
devServer.host,指定host。使用0.0.0.0可以让局域网内可访问。
devServer.hot,启用 webpack 的模块热替换特性(Hot Module Replacement)。
devServer.hotOnly,构建失败的时候是否不允许回退到使用刷新网页。
devServer.inline,模式切换。默认为内联模式,使用false切换到iframe模式。
devServer.open,启动webpack-dev-server后是否使用浏览器打开首页。
devServer.overlay,是否允许使用全屏覆盖的方式显示编译错误。默认不允许
devServer.port,监听端口号。默认8080。
devServer.proxy,代理,对于另外有单独的后端开发服务器API来说比较适合。
devServer.publicPath,设置内存中的打包文件的输出目录。区别于output.publicPath。

参考

webpack-dev-server使用方法,看完还不会的来找我~ 开发中 Server(devServer) Extra - Make your HTML hot reload gulp+browser-sync 监听文件实现浏览器自动刷新