14_webpack_devServe

当我们每次修改完成源代码之后都需要重新执行npm run build,这样子的开发效率是非常低下的

解决:通过watch监听源代码的变化

方式一:在build脚本的webpack中添加--watch选项

  "build": "webpack --watch"

当我们执行npm run build的时候,线程是阻塞在那里的,当你修改源代码的时候,它会自动构建

方式二:在webpack.config.js中添加watch选项:watch:true,那么就等同于方式一了

 

目前开发模式:
1.watch方案来监听文件的变化
2:通过live-server插件提供本地服务(当我们文件发生变化时,自动刷新页面)
效率不是特别高:
  1.对所有的源代码都重新进行编译
  2.编译成功后,都会生成新的文件(文件操作 file-system)
  3.live-server属于vscode插件(可能其他的编译器不具备)->不属于webpack给我们的解决方案
  4.live-server每次都会重新刷新整个页面

 

Webpack-dev-serve

安装:
npm i webpack-dev-serve -D

配置:
在package.json中的脚本中配置:

 "serve": "webpack serve"
这件事情其实是cli帮我们去完成的 cli分析到我们这里有这个参数,然后利用webpack-dev-serve库,帮我们启动整个webpack相关的服务

执行命令:
npm run serve

当我们修改源代码的时候,会对所有源代码进行重新编译,然后重新刷新整个页面

通过npm run serve指令,他是不会生成任何文件的
我们通过npm run serve命令,他是会编译代码的,他是把编译后的代码放到内存里面的,直接从内存中去加载性能会更高的

如何通过内存保存所有东西呢?
其实他早期用到了一个memory-fs(内存文件系统)的一个库(不更新了,webpack放弃了)
现在使用的是一个叫memfs库,把编译的文件通过这个库放到了内存里面,读取文件的时候直接在内存中读取性能会更高

当我们使用了webpack-dev-serve,它会先把资源进行构建,然后加入到内存中去,开启一个express服务,把我们请求的资源返回

 

 

Webpack-dev-middleware

开发过程中很少定义这个东西

默认情况下,webpack-dev-server已经帮助我们做好了一切;

  比如通过express启动一个服务,比如HMR(热模块替换);

  如果我们想要有更好的自由度(比如想更换koa),可以使用webpack-dev-middleware;

1.安装:
  npm i webpack-dev-middleware express(使用express中间件)
  npm i webpack-dev-middleware koa(使用koa中间件)

这里我使用的是express

2.创建server.js

const express = require("express");

const app = express();

app.listen(3000, () => {
  console.log("服务开启在3000端口");
});

上面的代码可以通过node server.js开启一个服务,但是开启的这个服务肯定是和我们的webpack是没有关系的

所以我们还需要做以下配置

 

const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");

const app = express();
//加载配置文件
const config = require("./webpack.config.js");
//传入配置信息,webpack根据配置信息进行编译
const compiler = webpack(config);
//传给webpack写好的中间件,进行处理,返回express的中间件
const middleware = webpackDevMiddleware(compiler);

app.use(middleware);

app.listen(3000, () => {
  console.log("服务开启在3000端口");
});

加载配置信息,把配置信息传给webpack,他会生成compiler的对象,把compiler的对象直接传给我们写好的中间件,它会处理返回给我们一个express的中间件,直接传给express

之后就会对源代码进行编译, 编译好之后,把编译好的东西放到express中间件中
当我们的浏览器去服务里面请求相关资源的时候会根据中间件(middleware)需要返回的数据给你返回

 

模块热替换(HMR)

Hot Module Replacement

模块热替换是指在 应用程序运行过程中,替换,添加,删除模块,而无需重新刷新整个页面;

通过以下几种方式,来提高开发的速度

  不重新加载整个页面,这样可以保留某些应用程序的状态不丢失
  只更新需要变化的内容,节省开发的时间
  修改了css\js源代码,会立即在浏览器更新,相当于直接在浏览器的devtools中直接修改样式

怎么使用HMR 

  首先不能使用webpack的watch选项和webpack-dev-middleware
  使用webpack-dev-serve启动服务,因为wds里面已经帮助我们封装好了HMR所需要的技术
  然后就是修改一个配置:webpack.config.js中添加一个devServer选项(专门为wds的配置),然后在里面添加一个指hot:true
  

  // 专门为webpack-dev-serve
  devServer: {
    hot: true,
  },

停掉当前的服务重新 npm run serve(每次修改完webpack.config.js都需要重新跑)

 

 

 有这个提示就代表开启了HMR

 

但是你会发现,当我们修改了某个一模块的时候,依然是刷新整个页面的

  这是因为我们需要去指定哪些模块发生更新时,进行HMR

import "./math";
console.log("Hello 1237778887");
console.log("abc");

if (module.hot) {
  /* 
  1.依赖(当前哪个模块发生变化的时候,你想去使用HMR,可以些多个或者数组),
  2.当模块更新之后,做的一些操作,当模块发生更新的时候,它会去回调这个参数
   */
  module.hot.accept("./math.js", () => {
    console.log("math Update...");
  });
}

这样子太麻烦了,如果有很多模块我都需要去每个都指定

 

Vue中的HMR

比如Vue项目,我们修改了组件,希望进行更新,这个时候应该如何去操作

社区已经帮我们解决了这个问题

Vue中我们使用vue-loader,此loader支持Vue组件的HMR,开箱即用

 

HMR的原理

webpack-dev-serve会创建两个服务:提供静态资源的服务(express)和Socket服务(net.Socket)

express server负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)

HMR SocketServer,是一个socket的长连接
  长链接有一个最好的好处是建立连接后双方可以通信,服务器可以直接发送文件到客户端
  当服务器监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk)
  通过长连接可以直接将这两个文件主动发送给客户端(浏览器)
  浏览器拿到这两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新

posted @ 2022-04-24 21:32  Mr-Hou88888  阅读(89)  评论(0编辑  收藏  举报