一文学会Webpack实用功能|针对不同环境的配置

Webpack 自动刷新的问题

在此之前呢我们已经简单了解了webpack-dev-server的一些基本用法和特性,那他主要就是为我们使用webpack构建的项目提供了一个比较友好的开发环境,和一个可以用来调试的开发服务器。那使用webpack-dev-server就可以让我们的开发过程更加专注于编码。

因为他可以监视到我们代码变化,然后自动进行打包,最后再通过自动刷新的方式,同步到浏览器,以便于我们可以及时的预览。

但是当你实际去使用这样的特性去弯沉具体的开发任务时那你会发现,这里还是会有一些不舒服的地方。

那例如这里是一个编辑器的应用,我想要在这里能够及时去调试编辑器中文本内容的样式,正常的操作肯定是先尝试在编辑器中添加一些文本作为展示样例。

然后我们回到开发工具当中找到控制这个编辑器样式的css文件。在这个编辑器样式文件中我们简单添加一些样式。那这个时候我们就能发现问题了,当我们修改完样式过后呢,原本想着可以及时看到最新的界面效果,但是这个时候我们编辑器中给的内容确没有了,那这里我们不得不再来编辑器中再去添加一些文本,如果说此时你对我们的样式还是不满意的话,那我们还需要继续来去调整样式,而且调整完了过后又会面临刚刚文本内容丢失这样一个问题。

那久而久之的话你就会发现,自动刷新这样一个功能还是很鸡肋,他并没有我们想象中那么好用。那这是因为我们每次修改完代码,webpack监视到文件变化就会自动打包,然后自动刷新到浏览器。

那一旦页面整体刷新,那页面中之前的任何操作状态都会丢失,所以说就会出现,刚刚我们所看到的这样一个情况。但是呢,聪明的人一般都会有一些小办法,例如我们可以在代码当中先去写死一个文本到我们的编辑器当中。那这样的话,即便是我们页面刷新也不会有丢失的这种情况出现。

那又或是我们通过一些额外的代码,把我们的内容先保存到临时存储中,然后刷新过后我们再去取回来。总之就是你有问题,我有办法。

那确实这些都是好办法,但是又都不是特别的好,因为这些都是典型的有洞补洞的操作,并不能根治我们页面刷新过后导致的页面数据丢失的这样一个问题。

而且这些方法都需要我们去编写一些跟我们业务本身无关的一些代码,那更好的办法自然是能够在页面不刷新的这种情况下我们代码也可以及时的更新进去。

那针对于这样的需求,webpack同样也可以满足,那接下来我们就一起去了解一下webpack当中如果去在页面不刷新的情况下及时的去更新我们的代码模块。

Webpack HMR 体验

HRM全称是Hot Module Replacement那翻译过来叫做,模块热替换或者叫做模块热更新。

那计算机行业我们经常听到一个叫做热拔插的名词,指的就是我们可以在一个正在运行的机器上随时去插拔设备,而我们机器的运行状态,是不会受插拔设备的影响。而且我们插上的设备可以立即开始工作,例如我们在电脑设备上的USB端口就是可以热拔插的。

那模块热替换的这个热,和我们刚刚提到的热拔插实际上是一个道理,他们都是在运行过程中的即时变化,那webpack中的模块热替换指的就是可以在应用程序运行的过程中实时的去替换掉我们应用中的某个模块。而我们应用的运行状态不会因此而改变。

例如我们在应用程序的运行过程中,我们修改了某个模块,那通过自动刷新就会导致我们应用整体的刷新,那应用中的状态信息呢,都会丢失掉。

而如果我们这个地方使用的是热替换的话,我们就可以实现,只将刚刚修改的这个模块,实时的去替换到应用当中,不必去完全刷新应用。

那这里我们可以先来对比一下使用热更新和使用自动刷新这两种方式的体验差异。

那屏幕显示的这个项目我们已经开启了HMR这个特性,那这里我们同样先在我们的页面当中随意去添加一些内容,也就是为我们的页面去制造一些运行的状态。

然后我们回到开发工具当中,这里我们尝试去修改我们文本的样式,我们先将它的颜色修改为红色,那保存过后呢,我们就可以立即看到新的样式结果。而我们的页面并没有整体的刷新。

那这种体验是非常友好的。对于项目中其他代码文件的修改,也可以有相同的热替换的这样一种体验。那我们这里再来尝试修改一下js文件。我们随意去修改一行js代码,然后保存。那此时呢我们浏览器当中,也没有刷新页面,而是直接执行了刚刚我们修改的这个模块。

那不仅如此,对于项目当中那些非文本文件,同样也可以使用热更新,那例如我们所显示的背景图片,我们通过简单的画图板来去修改一下这个图片。保存过后呢,我们浏览器当中同样也可以及时更新过来我们最新的这张图片,而我们整个应用的运行状态呢,也没有因此而发生变化。

那这就是HMR的作用和他的一个体验。

HMR可以算是webpack中最强大的特性之一,同时他也是最受欢迎的特性。因为他确实极大程度的提高了开发者的工作效率,所以说我们接下来要重点来去看,如何去使用HMR

Webpack 开启 HMR

热更新这么强大的功能而言,他的使用并不算特别的复杂,接下来我们就一起来了解下具体如何去使用HMR。

HMR已经集成在了webpack-dev-server工具当中,所以说我们就不需要再去单独安装什么模块了。

那使用这个特性呢,我们需要去运行webpack-dev-server这个命令时通过–hot这样一个参数去开启这样一个特性,或者也可以在配置文件当中去添加对应的配置来去开启这样一个功能。

我们打开配置文件。这里我们需要配置的地方有两个,第一个我们要将dev-server中的hot属性设置为true。

然后我们需要载入一个插件,那这个插件是webpack内置的一个插件,所以我们这里先去导入webpack模块,那有了这个模块过后呢,我们这里使用的是这个模块当中的hot-module-replacement-plugin这样一个插件。

我们把这个插件配置进来。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
   
    mode: 'development'
    entry: './src/main.js',
    output: {
   
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist'),
        // publicPath: 'dist/'
    },
    devtool: 'source-map',
    devServer: {
   
        hot: true
    }
    module: {
   
        rules: [
            {
   
                test: /.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
   
                test: /.png$/,
                use: 'file-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
   
            title: 'Webpack Plugin Sample',
            template: './src/index.html'
        }),
        new webpack.HotModuleReplacementPlugin()
    ]
}

配置完成过后我们打开命令行终端,因为我们已经开启了HMR,所以我们这里直接去运行webpack-dev-server 然后去启动weboack开发的服务器。

yarn webpack-dev-server

接下来我们就可以在浏览器去体验HMR带来的优势了,我们回到开发工具当中,这里我们先尝试修改一下样式文件,那保存过后这个样式模块就可以以热更新的方式直接去作用到我们的页面当中了。

然后呢我们再来尝试修改一下js模块文件,我们在js中随便console.log一句话,此时我们就会发现,这里的页面却自动刷新了。并没有刚刚我们所看到的那种热更新的体验。

我们再在页面的编辑器当中去添加一些文字,这样的话我们可以更容易去确认是否有刷新,完成过后我们再回到开发工具当中。修改文件,我们发现页面真的刷新了。

我们可以发现样式文件有变动可以实现热更新,但是js文件的修改就失去了作用,那具体我们该如何去实现所有模块资源的热替换,我们接着往下看。

Webpack HMR 的疑问

我们发现了模块热替换确实提供了非常友好的开发体验,但是当我们自己尝试开启HMR过后呢,我们发现效果确不尽如人意,那这里是因为HMR他并不像webpack其他的特性一样可以开箱即用。

也就是说我们的HMR还需要我们做一些额外的操作才能够可以正常工作,那webpack中的HMR需要我们手动通过代码去处理当模块更新过后我们需要如何把更新过后的模块去替换到我们运行的页面当中。

那可能会有人问,为什么当我开启了HMR过后我们的样式文件就可以直接去热更新,我们好像也没有手动的去处理样式模块的更新。

这是因为样式文件是经过loader处理的,在style-loader里面就已经自动处理了样式文件的热更新,所以说我们就不需要我们自己去额外做手动的操作。

可能你会想,凭什么样式文件就可以自动处理,而我的脚本文件就需要我们自己手动处理呢,这个原因也很简单,因为样式模块更新过后呢,他只需要把更新过后的css及时的替换到页面当中,他就可以覆盖掉之前的样式,从而实现样式文件的更新。

而我们所编写的javaSciript的模块他是没有任何规律的,因为你可能在一个模块中导出的是一个对象,也有可能是一个字符串,还有可能导出的是一个函数,那我们对导出的这个成员我们的使用也是各不相同的。

所以说webpack面对这些毫无规律的js模块,他就根本不知道,如何去处理更新过后的模块,那也就没有办法帮你实现一个通用所有模块的替换方案。

这就是为什么样式文件可以直接热更新,而js文件更新过后我们页面还是自动刷新的原因。

那可能有一些使用过vue-cli或者是create-react-app的一些脚手架工具的人来说,他会觉得,我的项目当中并没有手动的去处理我们js模块的更新,我的代码照样可以做热替换,没有我们刚刚说的这么麻烦。

那这是因为你使用的是框架,那我使用框架开发时,我们项目中每个文件他自然就有了规律,因为框架他提供的就是一些规则,例如我们再react模块中要求每一个模块必须要去导出一个函数,或者是导出一个类。

那有了这样一个规律那就可能会有通用的替换办法,例如每一个文件导出的都是一个函数的话那他就自动的把这个函数再拿回来再去执行一下。

而且这些工具内部都已经帮你提供好了这种通用的HMR替换模块,所以说我们就不需要自己手动处理了,如果你之前没有接触过这样的工具,也无所谓,你可以忽略掉这一条。这并不影响我们后面的理解。

综上所述,我们还需要自己手动处理当JS模块更新过后我们需要去做的事情。

Webpack 使用 HMR API

Hot-module-replacement-plugin为我们js提供了一套用于去处理HMR的api,我们需要在自己的代码中去使用这套api来去处理当某一个模块更新过后应该如何替换掉当前正在运行的页面当中。

接下来我们一起回到代码当中,尝试通过HMR的api来去手动处理模块更新过后的热替换,我们打开js。

这是我们打包的入口文件。也就是在这个文件当中才开始去加载其他的模块,那就是因为这个模块当中使用了这些导入的模块,那一但当这些模块更新了过后,我们就必须要去重新使用这些模块。

所以说我们要在这个模块中去处理他所依赖的这些模块更新过后的热替换。

在这套API当中,他为我们的module对象提供了一个hot属性,那这个属性也是一个对象,他就是我们HMR API的核心对象,那他提供了一个accept方法,用于去注册,当我们某一个模块更新过后的处理函数。

那这个方法的第一个参数接收的就是我们依赖模块的路径,第二个参数就是依赖路径更新过后的处理函数。

我们这里先来尝试注册一下当我们的editor模块更新过后的处理函数。那这里第一个参数就是editor模块的路径,然后第二个参数呢,我们传入一个函数。然后在这个函数中我们去打印一个消息,表示一个editor模块更新了。

import createEditor from './editor';
import background from './better.png';
import './global.css';

const editor = createEditor();
document.body.appendChild(editor);

const img = new Image();
img.src = background;
document.body.appendChild(img);

module.hot.accept('./editor', () => {
   
    console.log('editor 模块更新了,需要这里手动处理');
});

完成过后我们打开命令行启动webpak-dev-server回到浏览器打开开发人员工具。

那这

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值