zoukankan      html  css  js  c++  java
  • webpack hmr

    参考:

    https://webpack.js.org/concepts/hot-module-replacement/

    https://webpack.js.org/guides/hot-module-replacement/

      hmr技术支持程序运行时的模块(amd、commonJS等)的修改、添加和删除,而不用整个程序重新加载,这可以提升开发的效率:

    1. hmr后程序的状态可以得到保存
    2. 仅仅改变变化的部分,其余不变
    3. 调样式更加快捷,基本比得上在浏览器中的样式修改

      以下步骤允许模块在应用程序中切换:

    1. app请求hmr runtime来检查模块更新
    2. runtime异步下载更新和通知app
    3. app请求runtime去应用这些更新
    4. runtime同步地应用这些更新

    在编译器中

      编译器需要提交一个update来执行更新,更新的内容有如下两部分:

    1. 清单文件(json),包含了新的编译hash和要更新的chunk列表。
    2. 一个或多个chunk(js),每个chunk包含了所有要更新的模块的新代码(或者一个标志位代表模块要被移除)

      编译器能保证这些模块和chunk的id在构建中始终是唯一的,这些id保存在webpack-dev-server的内存中,也可以保存在一个json文件中。

    在模块中

      hmr是一个可选的功能,仅仅会影响包含了hmr代码的模块。如style-loader实现了hmr接口,当它受到一个hmr的更新,这个loader就会去用新的样式去替换旧的样式。

      当在模块中实现hmr接口,我们可以决定当模块需要更新的时候,让模块去做我们想做的事情。当模块没有写hmr时,对应的更新就会被往上冒泡,会导致整颗依赖树都被重新加载。

      对于module.hot 的更多信息可以在 HMR API page 查看。

    在运行时

      这里关注的是更加细节的东西,如果不感兴趣,可以直接去了解 HMR API page 或者 HMR guide

      对于模块系统的运行,额外的代码用于追踪模块parents和children。有两个方法check和apply可以用来管理。

      check:创建一个http请求来更新清单文件。http请求失败的话则更新不可用,请求成功的话,一个新的chunk列表会用于与当前已经加载好的chunk进行对比,当所有需要更新的chunk已经下载好而且准备好了,则进入ready状态。

      apply:这个函数把所有的模块标记为不可用,不可用的模块或者父模块需要有一个update handler,否则这个这个标记会冒泡,使所有的祖先模块被标记为不可用。标记会一直冒泡,直到到达app的入口文件或者被update handler所处理。

      最后,所有的不可用模块都被配置(通过dispose handler)和卸载,当前的hash值被更新,所有的accept handler都被调用。hmr rumtime到这里切换为空闲状态。

    webpack-dev-server

      webpack-dev-server通过hot模式来支持hmr。以下记录以下步骤:

    1. 使bundle的内存输出路径与硬盘路径一致,具体可以去参考 自动刷新
    2. 然后启用插件
      plugins: [
          new webpack.NamedModulesPlugin(),
          new webpack.HotModuleReplacementPlugin()
      ]
    3. 启用devServer的hot模式
      devServer: {
          hot: true
      }
    4. 在模块中进行处理
      if(module.hot){
          module.hot.accept("./modules/utils",function(){
              console.log("当上面的模块发生修改,这里的代码会执行")
          })
      }
    5. 最重要的一点,导入的模块不能使用require,而是使用import .. from形式。以上回调函数执行的时候,可以认为导入的内容已经发生变化(ES6只读地址指向的内容已经变化,可以直接使用)

      对于样式的处理,以上123点,接着配置添加style、css-loader,然后在入口文件中引入样式:import './stl.css'  这样配置之后,修改样式文件,浏览器界面马上发生变化,效果就像是F12来修改样式一样。

    React Hot Loader

    按照 文档 的步骤:

    配置文件

    var path = require('path');
    const webpack = require('webpack')
    module.exports = {
        entry: {
            app:['react-hot-loader/patch', './main.jsx']
        },
        plugins: [
            new webpack.NamedModulesPlugin(),
            new webpack.HotModuleReplacementPlugin()
        ],
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
            publicPath:"dist"
        },
        devServer: {
            contentBase: '.',
            hot: true
        },
        module: {
            rules: [
                {
                    test: /.jsx?$/,
                    exclude: /(node_modules|bower_components)/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: [["es2015", { "modules": false }],'react'],
                            plugins:["react-hot-loader/babel"]
                        }
                    }
                }
            ]
        }
    };
    View Code

    入口文件

    import React from 'react'
    import ReactDOM from 'react-dom'
    import { AppContainer } from 'react-hot-loader'
    import App from './App.jsx'
    
    const render = Component => {
        ReactDOM.render(
            <AppContainer>
                <Component />
            </AppContainer>,
            document.getElementById('root')
        )
    }
    
    render(App)
    
    if (module.hot) {
        module.hot.accept('./App.jsx', () => {
            render(App)
        })
    }
    View Code

    App.jsx

    import React from "react"
    export default class App extends React.Component{
        render(){
            return <div>123</div>
        }
    }
    View Code

    依赖

    {
      "name": "h2",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "srv": "webpack-dev-server",
        "build": "webpack"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-react": "^6.24.1",
        "react": "^16.2.0",
        "react-dom": "^16.2.0",
        "react-hot-loader": "^3.1.3",
        "webpack": "^3.10.0",
        "webpack-dev-server": "^2.10.1"
      }
    }
    View Code

      实践的时候发现有一点很重要:要求webpack和webpack-dev-server必须都在本地安装,而不是一个全局安装,一个本地安装。否则会导致热更新无效,而且不报错,bundle.js引入了不同的文件:

      两个都本地本地安装就可以解决问题了,再次查看bundle.js,引用的emitter.js路径就都一样了。

    Vue Loader

    其他链接

    https://juejin.im/post/5a41ab5b51882560b65290eb

    https://zhuanlan.zhihu.com/p/30669007

  • 相关阅读:
    [linux]CentOS防火墙
    [工具]VIM键位
    [mac]mac 终端 常用命令
    [数据结构]“堆”,"栈","堆栈","队列"的区别
    [java]Java构造方法与析构方法
    [环境]Eclipse安装WindowBuilder
    [BZOJ 1441]Min(裴蜀定理)
    [BZOJ 4563][Haoi2016]放棋子(错排公式)
    [BZOJ 4517][Sdoi2016]排列计数(组合数学/错排公式)
    [BZOJ 3680]吊打XXX(模拟退火)
  • 原文地址:https://www.cnblogs.com/hellohello/p/8260486.html
Copyright © 2011-2022 走看看