代码沿用webpack学习之1.基础配置

每次要编译代码时,手动运行 npm run build 就会变得很麻烦。

webpack 中有几个不同的方式,可以在代码发生变化后自动编译代码:

  1. webpack’s Watch Mode 观察模式
  2. webpack-dev-server
  3. webpack-dev-middleware

1.使用观察模式 watch

webpack 的 --watch 命令可以监听(watch) 依赖图中的所有文件以进行更改。如果其中一个文件被更新,代码将被重新编译,所以你不必手动运行整个构建。

添加一个用于启动 webpack 的观察模式的 npm script 脚本:

// package.json
{   "scripts": {"build": "webpack","watch": "webpack --watch",// ...},// ...
}

运行 npm run watch 后,发现终端还在保持运行。
在浏览器查看到 module2.js中的报错。
然后删除 抛错 代码并保存:

// src/module2.js
export var message = 'this is module2';class Person{show() {// throw new Error('this is a mistake') // 将这行注释console.log('My name is Jack');}
}
let p = new Person;
p.show();

发现终端自动重新打包了一次。
刷新页面,代码更新,错误被去掉了。
使用 --progress 命令 百分比查看编译打包进度。

webpack --watch --progress

缺点

1.自动编译,需手动刷新页面才能查看效果。
2.一个文件变更,重新打包整个项目。

2.使用webpack-dev-server

webpack-dev-server 可以实现:
1.提供一个简单的 web 服务器,以本地站点方式访问。默认端口8080,访问地址:http://localhost:8080
2.监听变更,自动编译。
3.监听变更,实时 重新加载(live reloading)。

需要安装:

npm install --save-dev webpack-dev-server

配置webpack-dev-server
devServer.contentBase 告诉服务器从哪里提供打包之外的文件,打包的文件存储在内存映射到这个目录下。
类似配置站点根目录:告诉开发服务器(dev server),在哪里查找文件。
index.html作为手动创建的静态文件,需要指定服务器去dist下访问它。

// webpack.config.js
// ...
module.exports = { devServer: {contentBase: : path.resolve(__dirname, './dist') // 推荐使用绝对路径},// ...
}// package.json
{   "scripts": {"build": "webpack","watch": "webpack --watch --progress","start": "webpack-dev-server --open --progress",// ...},// ...
}

webpack-dev-server 命令用于运行,–open命令用于开始运行后自动打开浏览器访问默认地址:http://localhost:8080

运行脚本 npm run start 查看效果同 watch 一样,并实现了自动刷新页面

对比watch优点

1.重新编译后,自动加载页面(优化了watch的第一个缺点)
2.编译的代码存储在内存中,而不是生成bundle到output目录。(优化了watch的第二个缺点)
可以删除打包后的文件,重新运行webpack-dev-server,依然可以正常访问。
注:示例中dist/index.html是手动创建的,不是编译的文件。若使用html-webpack-plugin生成,也将被存入内存。

缺点

1.重新编译,以刷新页面方式加载更新的内容,无法保留页面状态。
2.封装好的express

3.使用webpack-dev-middleware

node_modules/webpack-dev-server/lib/server中可以看到,webpack-dev-server是使用express搭建的服务器,然后内部使用 webpack-dev-middlewareWebSocket 实现实时重新加载(LiveReload)。

webpack-dev-middleware 是一个容器(wrapper),它可以把 webpack 处理后的文件传递给一个服务器(server)。

简单搭建

现在单独使用 webpack-dev-middlewareexpress 来实现 LiveReload,以提供更多自定义配置的空间。

安装

npm install -D webpack-dev-middleware express

配置 express 服务,在根目录下创建server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config); // 编译器// 告诉express使用webpack-dev-middleware
app.use(webpackDevMiddleware(compiler));// 告诉express访问静态资源的路径,类似配置webpack-dev-server的devServer.contentBase
app.use(express.static('dist'))// 在8080端口运行文件
app.listen(8080, function () {console.log('Example app listening on port 8080!\n');
});

添加一个 npm script,以使我们更方便地运行服务:

// package.json
{   "scripts": {"server": "node server.js",// ...},// ...

执行 npm run server ,手动在浏览器访问 http://localhost:8080
修改模块中的代码保存,手动刷新页面查看效果

至此,已经实现了下面几个功能:
1.搭建了一个简单的服务器。
2.修改模块,实时编译。
3.编译文件存储在内存,未写入磁盘

未实现的功能:
1.实时重载
2.运行服务,自动打开浏览器(可使用open模块实现,本学习不使用)

模块热替换HMR (hot module replacement)

使用模块热替换实现实时重载,与webpack-dev-server的区别是,HMR以模块为单位重载,保留页面的状态。

实际效果,比如:
一个页面包含label和input表单,input中输入内容,这时修改模块令label的文本内容改变webpack-dev-server会刷新页面,input被清空。
而使用HMR,label实现更新,且页面未刷新,input未清空。

安装并配置

安装 webpack-hot-middleware

npm install --save-dev webpack-hot-middleware

webpack.config.js中启用HMR。
在入口前面添加 webpack-hot-middleware/client,它连接到服务器,在包重新构建时接收通知,然后相应地更新客户端的包。

// webpack.config.js 启用HMR
// ...
var webpack = require('webpack');
const hotMiddlewareScript = 'webpack-hot-middleware/client?quiet=true'; // quiet禁用console日志
module.exports = {// ...// devServer: {//     contentBase: path.resolve(__dirname, './dist')// }, // 不用webpack-dev-server,可以注释掉这段entry: {main: [hotMiddlewareScript , './src/index.js'],util: [hotMiddlewareScript , './src/util.js']},plugins: [new webpack.HotModuleReplacementPlugin() // 使用webpack的插件接口开启HMR// ...]
}

告诉express在同一个编译器中使用webpack-hot-middleware

// server.js
// ...
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware')// ...// 告诉express使用webpack-dev-middleware并使用webpack.config.js
app.use(webpackDevMiddleware(compiler));app.use(webpackHotMiddleware(compiler));// ...

添加html内容查看效果

现在项目中有个两个入口模块,只修改util.js令其实现热重载,html添加内容查看效果

// src/util.js
window.onload = e => import('./module3.js').then(module => {let show = module.default;show();
});// 修改button文本查看页面变更
var btn = document.getElementById('btn');
btn.innerText = '输出';if (module.hot) {// 接受模块的更新,并更新页面中的内容module.hot.accept()
}// dist/index.html
// 添加内容
<input type="text" />
<button id="btn"></button>// src/index.js
// 此文件未改动,在此展示做对比
import './css/style.css';
import data from './module1';var div = document.createElement('div');
div.innerHTML = `<h1>${data.title}</h1><p>${data.info}</p>`;
document.body.appendChild(div);

运行 npm run server 浏览器访问dist/index.html,在input中输入内容
修改util.js中的button文本并保存,看到页面未刷新,input中内容依然保留,而button的文本实现了更新。

修改index.js中的innerHTML,页面未刷新,内容也没有变化。
查看控制台Console,发现有一条信息:
Ignored an update to unaccepted module 18 -> 14
忽略对未接受模块18->14的更新
原因是,在模块index.js中未用module.hot.accept接受此模块的更新。

尽管如此,模块index.js也完成了重新编译,手动刷新页面可以看到变化。
也可以通过 HMR客户端配置 reload,对accept未接受更新的模块,执行页面重载

// webpack.config.js
const hotMiddlewareScript = 'webpack-hot-middleware/client?quiet=true&reload=true';

module.hot.accept

如果已经通过 HotModuleReplacementPlugin 启用了模块热替换(Hot Module Replacement),则它的接口将被暴露在 module.hot 属性下面。

accep 接口 接受模块的更新,完成页面同步更新,并可以定义一个回调函数响应模块的更新。

accep(callback) 接受将当前模块(accept所在js)的更新
accep(dependencies, // 指定接受哪些模块的更新,可以是一个字符串或字符串数组,例:'./module3.js'callback // 用于在模块更新后触发的函数
)

css未更新

修改style.css文件发现出发了重新编译,未触发热替换。
原因是loader未配置,如果未使用css分离,直接用style-loader,可以实现hmr。
不过当前代码,使用了MiniCssExtractPlugin预处理,所以需要手动配置开启hmr:

// webpack.config.js
// ...module: {rules: [{test: /\.css$/, // 根据正则匹配.css结尾的文件use: [ // 配置loader,倒序使用{loader: MiniCssExtractPlugin.loader,options: {hmr: true // 一般在开发环境开启hmr process.env.NODE_ENV === 'development'}},{ loader: 'css-loader' }]}]},
// ...

副作用

在index.js中使用accept,使其实现HMR。

// src/index.js
import './css/style.css';
import data from './module1';// 调用位置随意
if (module.hot) {module.hot.accept()
}var div = document.createElement('div');
div.innerHTML = `<h1>${data.title}</h1><p>${data.info}</p>`;
document.body.appendChild(div);

修改index.js中的innerHTML,页面内容更新,但是之前的内容依然保留。
所以模块被热更新,之前的仍然可能会在客户端留下痕迹,例如:操作dom、事件绑定、计时器等。
这些痕迹可以在accept的回调中处理掉,当然,最方便的就是手动刷新页面。

参考

开发 | webpack
express
webpack-dev-middleware
webpack-hot-middleware

webpack学习之2.自动编译、实时重载LiveReload、热替换HMR相关推荐

  1. webpack实践之路(七):模块热替换HMR

    HMR 模块热替换(Hot Module Replacement 或 HMR)允许在运行时更新各种模块,而无需进行完全刷新. HMR主要是通过以下几种方式,来显著加快开发速度: 保留在完全重新加载页面 ...

  2. 修改html时webpack热更新,webpack学习之路(二)webpack-dev-server实现热更新

    上一章对webpack的配置有了简单的认识. 这一章,我需要学习的是webpack热更新,因为在开发过程中,不希望当文件更改时,人肉去编译文件,刷新浏览器. webpack热更新 webpack-de ...

  3. webpack学习之路(四)webpack-hot-middleware实现热更新

    上一节我学习了webpack-dev-middleware,但是单独使用它并没有实现热更新,所以这节我要学习搭配使用webpack-hot-middleware,来实现热更新功能. 创建项目 我们依然 ...

  4. webpack 3 零基础入门教程 #12 - 如何使用模块热替换 HMR 来处理 CSS

    模块热替换 是什么意思? 以前我们使用的 webpack --watch 或 webpack-dev-server 的功能是监听文件改变,就自动刷新浏览器,而这个 模块热替换 不用刷新浏览器,它是只让 ...

  5. webpack 项目使用webpack-dev-server 自动编译 (2)

    在上一篇的博客中我们使用webpack 创建了一个项目 创建webpack 项目(1) https://blog.csdn.net/datouniao1/article/details/1194269 ...

  6. 深度学习自动编译和优化技术调研

    深度学习自动编译和优化技术调研 转自:https://moqi.com.cn/blog/deeplearning/ 作者:墨奇科技全栈开发 在墨奇科技,我们需要将一些包含深度神经网络(DNN)的 AI ...

  7. webpack学习之路

    webpack学习之路 当自己在学习webpack的时候,在网上发现中文的很详细的教程很少,于是便想将自己学习webpack的笔记记录整理下来,便有了这篇文章,希望对大家有所帮助,如果有错误,欢迎大家 ...

  8. webpack学习笔记 (三) webpack-dev-server插件和HotModuleReplacementPlugin插件使用

    webpack-dev-server插件 webpack-dev-server是webpack官方提供的一个小型Express服务器.使用它可以为webpack打包生成的资源文件提供web服务. we ...

  9. Hot Module Replacement热更新(webpack学习篇9)

    模块热替换(HMR - Hot Module Replacement)作用:是指在应用程序运行过程中替换.添加或删除模块,而无需重新加载整个页面.主要是通过以下几种方式,来显著加快开发速度: 保留在完 ...

最新文章

  1. 跟我学雨林木风系统制作——2.涉及的技术及用到的工具介绍
  2. UIScrollView 使用
  3. UVa1377 Ruler(dfs或者bfs)
  4. 学会数据库读写分离、分表分库
  5. 走进移动web开发的四大框架
  6. java ftp 中文上传_java实现ftp文件上传下载,解决慢,中文乱码,多个文件下载等问题...
  7. 高并发第一弹:准备阶段 了解高并发
  8. MYSQL——《数据库》实验壹——熟悉数据库管理工具、数据库和表的基本操作
  9. 12岁上大学,23岁获博士学位,这位天才科学家正式加盟清华
  10. 三星a9s参数_三星A9s配置怎么样 三星A9s参数配置介绍
  11. Anagrams by Stack(进栈出栈问题)
  12. 机器视觉经典案例-表面划伤检测案例
  13. Labview2019安装
  14. Win10 64位系统运行汇编程序(使用masm与dosbox)
  15. 运维服务器环境梳理方案,运维工作梳理
  16. Contrastive Adaptation Network for Unsupervised Domain Adaptation
  17. F.conv2d pytorch卷积计算
  18. 05.ThreeJs开发指南-第五章-几何体
  19. Win10 WSL2 linux 子系统安装Docker
  20. 推荐系统 | 威尔逊区间法

热门文章

  1. 【C】二叉树--顺序结构(详解堆的实现,topK排序、堆排)、和链式结构(链式结构的遍历、链式结构常见递归操作以及练习题)
  2. 一个自己开发的并应用在很多项目里的unity关卡编辑器
  3. java - FileUtils类
  4. 使用ECharts map,实现省、市、区县、乡镇自定义地图
  5. Lumion 和 Vray这2款渲染器哪个更强?
  6. CHRONY - 时钟同步
  7. 我国典型电子垃圾拆解地持久性有毒化学污染物污染现状
  8. 谁说.NET没有GC调优,只改一行代码就让程序不再占用内存
  9. 微信小程序+云开发 实现表单数据提交到云开发的数据库里面
  10. 如何评价《自卑与超越》这本书?