webpack 教程 那些事儿03-webpack两大精华插件,热加载

本节主要讲述 webpack的两大经典开发调试插件,热插拔内存缓存机制

文章目录

  1. 1. html-webpack-plugin插件的使用
  2. 2. webpack-dev-middleware 插件登场
  3. 3. webpack-hot-middleware 为了左手
  4. 4. 实现html模版更改自动刷新
  5. 5. 本案例测试源码下载

html-webpack-plugin插件的使用

如果没记错,上篇的时候构建完成的js文件是我们在页面用 script 标签手动引入的, 聪明的您应该马上看出问题来了,难道每次更改输出path,都要手动更新引入链接吗?如果加上 hash防止缓存,那么一串,岂不头疼欲死。有需求就有解决方案,此款插件就是用来 将依赖自动写入html文件的。

1
sudo cnpm i html-webpack-plugin --save-dev

修改配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 终于动用了配置文件里的 plugins 功能选项,已经快遗忘在角落了
plugins: [
new HtmlWebpackPlugin({
filename: '../index.html',
//渲染输出html文件名,路径相对于 output.path 的值
 
template: path.resolve(__dirname, './app/views/index.html'),
//渲染源模版文件
 
inject: true
//这个东西非常重要,true: 自动写入依赖文件; false: 不写入依赖,构建多页面非常有用
})
]
 
# 自动写入依赖,所以删除app/views/index.html 的script标签链接
<body>
<mountain></mountain>
</body>
# 执行命令: webpack
webpack

查看output目录,发现多了一个 index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
background: #f90;
}
h2{
text-align: center;
font-size: 30px;
padding: 10px 0;
}
</style>
</head>
<body>
<mountain></mountain>
<script type="text/javascript" src="static/app.js"></script></body>
</html>
# 上面的script就是自动写入的依赖,src路径就是 配置文件中 output.publicPath
# 终于用到了这个调试功能

用chrome 打开链接http://localhost:3000/output/index.html 可以看到一样的屎黄色结果

可能聪明的您又发现了一个问题,我们每次改动一句代码,哪怕更改一个字体大小,几像素留白,就要编译打包一次才能看到结果,有没有好烦呢?

webpack-dev-middleware 插件登场

1
sudo cnpm i webpack-dev-middleware --save-dev

此插件主要结合 express的 中间件使用,修改dev-server.js,方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var express = require("express");
var app = express();
var port = process.env.PORT || 3000;
 
/**
* 引入webpack 及其 配置config
*/
var webpack = require("webpack");
var webpackConfig = require("./webpack.config.js");
//调用配置,生成 compiler instance
var compiler = webpack(webpackConfig);
 
//这里是重点,使用 webpack-dev-middleware 插件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
chunks: false
}
})
// 注册中间件
app.use(devMiddleware);
 
// 使用静态资源
app.use(express.static(__dirname+'/'));
 
app.listen(port, function (err){
if (err) {
throw err;
}
console.log('Listening at http://localhost:' + port + '\n')
})

为了方便调试 和 理解什么叫 内存缓存,不写入硬盘,我们修改一点webpack配置

  • 修改 output.publicPath: “/“,修改为根目录
  • plugins中的filename: “index.html” ,置换到根目录
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    output: {
    path: path.resolve(__dirname, "./output/static"), //输出路径
    publicPath: '/', //调试或者 CDN 之类的域名,稍候会用到
    filename: "[name].js" //配置生成的文件名
    }
     
    plugins: [
    new HtmlWebpackPlugin({
    filename: 'index.html',
    template: path.resolve(__dirname, './app/views/index.html'),
    inject: true
    })
    ]

然后,重启服务 node dev-server.js

打来浏览器输入: http://localhost:3000/index.html
哇塞,又看到了记忆中 屎黄色 的界面,有木有很开心,打开控制台,会看到这句代码

1
<script type="text/javascript" src="/app.js"></script>

惊奇的事情发生了,我们的根目录根本没有index.html 和 app.js,这些东西哪里来的呢?
这就是我们的 伟大的中间件 webpack-dev-middleware 的功劳。

然后去mountains.vue文件中修改背景色或者其他,然后刷新浏览器就能看到效果了
有木有很赞,速度还超快哦,如图改动了背景色,只需 55ms,就是快
webpack 教程 那些事儿03-webpack两大精华插件,热加载time

接下来就是解放我们的双手,自动实时刷新页面.

webpack-hot-middleware 为了左手

1
2
# 老套路 install
sudo cnpm i webpack-hot-middleware --save-dev

使用步骤,参照api,很简单

  • 增加插件plugins

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 注意先行引入 webpack
    # var webpack = require("webpack");
    plugins: [
    // Webpack 1.0
    new webpack.optimize.OccurenceOrderPlugin(),
    // Webpack 2.0 fixed this mispelling
    // new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new HtmlWebpackPlugin({
    filename: 'index.html',
    template: path.resolve(__dirname, './app/views/index.html'),
    inject: true
    })
    ]
  • Add ‘webpack-hot-middleware/client’ into the entry array(添加xx到入口数组)

    1
    2
    3
    4
    entry: {
    app: ['webpack-hot-middleware/client',path.resolve(__dirname, "./app/main.js")]
    }
    更好的方法是不动基本配置,稍候会在dev-server.js中 书写
  • Add webpack-hot-middleware attached to the same compiler instance

    1
    2
    # dev-server.js中 app.use(devMiddleware); 之后增加
    app.use(require("webpack-hot-middleware")(compiler));

重新启动服务 node der-server.js
然后修改一个 body 背景,切回浏览器,哇塞,自动刷新了
怀着激动的心情改了一下main.js,开心的切回浏览器哇靠靠,一切都没变化,错觉?果然手动刷新, 看到了你想看到的。
你没错,是我错了,更改上面第二部的 entry参数配置如下:

1
2
3
4
# 增加 参数reload=true
entry: {
app: ['webpack-hot-middleware/client?noInfo=true&reload=true',path.resolve(__dirname, "./app/main.js")]
}

果然重启服务,一切ok.
闲的蛋疼又去,更改了.vue文件里面的 data 数据,然后。。。。问题又来了,无热加载,控制台却能看到vue文件变化消息
查了查资料:发现这可能是vue的热加载机制和策略问题,目前我不知道怎么解决。

接下来还有一件事,那就是html模版改动的自动刷新,现在是没有这个功能的,不信你试试!

实现html模版更改自动刷新

  • 更改entry注入参数方式,从dev-server.js写入,example:
1
2
3
4
# webpack.config.js 恢复初始设置
entry: {
app: path.resolve(__dirname, "./app/main.js")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# dev-server.js
# 增加文件,刷新client单独文件配置,配合html reload
var express = require("express");
var app = express();
var port = process.env.PORT || 3000;
 
/**
* 引入webpack 及其 配置config
*/
var webpack = require("webpack");
var webpackConfig = require("./webpack.config.js");
 
// var devClient = 'webpack-hot-middleware/client?noInfo=true&reload=true';
var devClient = './dev-client';
Object.keys(webpackConfig.entry).forEach(function (name, i) {
var extras = [devClient]
webpackConfig.entry[name] = extras.concat(webpackConfig.entry[name])
})
//调用配置
var compiler = webpack(webpackConfig);
 
//这里是重点,使用 webpack-dev-middleware 插件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: '/',
stats: {
colors: true,
chunks: false
}
})
 
var hotMiddleware = require('webpack-hot-middleware')(compiler)
// 监听html文件改变事件
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
// 发布事件 reload,这个事件会在dev-client.js中接受到,然后刷新
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
 
 
// 注册中间件
app.use(devMiddleware);
app.use(hotMiddleware);
 
// 使用静态资源
app.use(express.static(__dirname+'/'));
 
app.listen(port, function (err){
if (err) {
throw err;
}
console.log('Listening at http://localhost:' + port + '\n')
})

dev-client.js 接受reload事件

1
2
3
4
5
6
7
8
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
// 订阅事件,当 event.action === 'reload' 时执行页面刷新
// 还记得 dev-server.js中 派发的reload事件吧
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

重启服务,修改试试?不出意外,应该万事大吉了。
ok,至此,测试程序已经结束了。下篇讲解项目中的webpack配置.

本案例测试源码下载

上一篇:[转帖] 中国SaaS死或生之二: ERP两大邪术,尽出歪门邪路 ---- 挺好玩的


下一篇:BZOJ 1193 [HNOI2006]马步距离:大范围贪心 小范围暴搜