• 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 + ' ')
    })

    为了方便调试 和 理解什么叫 内存缓存,不写入硬盘,我们修改一点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,就是快
    timetime

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

    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 + ' ')
    })

    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配置.

    本案例测试源码下载

  • 相关阅读:
    [Angular] Using the platform agnostic Renderer & ElementRef
    [HTML5] Focus management using CSS, HTML, and JavaScript
    [TypeScript] Increase TypeScript's type safety with noImplicitAny
    [React] displayName for stateless component
    [Redux] Important things in Redux
    [HTML5] Using the tabindex attribute for keyboard accessibility
    [Angular] @ViewChild and template #refs to get Element Ref
    [Angular] @ViewChildren and QueryLists (ngAfterViewInit)
    [Angular] Difference between Providers and ViewProviders
    [Angular] Difference between ngAfterViewInit and ngAfterContentInit
  • 原文地址:https://www.cnblogs.com/donglegend/p/5821092.html
Copyright © 2020-2023  润新知