react-hot-loader的使用方式

webpack中提供了热模块更新的功能,在不刷新整个页面的情况下来替换某些更变的组件,而这样做的最大的好处就在于状态的保存。比如我们前面在输入框中输入的内容,就不会在我们热模块替换以后被刷新掉,让我们要重新再输入一次了。

而react的构建现在一般还是基于webpack的,webpack也提供了对应的插件。react-hot-loader

https://github.com/gaearon/react-hot-loader

跟着github上面的例子我们就可以很快进行搭建了。

这里要注意几点。

我们创建项目的时候是类似creat-react-app的方式创建项目的。

creat-react-app的创建方式是有两个js文件,一个是index.js,一个是App.js

App.js是根组件,而index.js才是来执行初始化以及渲染这些工作的。而我们有的时候是把这两个合二为一了。这样就跟官网的对不上会有点。

下面给出一个demo来进行配置



目录结构

App.jsx

import React from 'react';
import { hot } from 'react-hot-loader';
import { Hello } from './components/hello.jsx';
require('./font.js');

class App extends React.Component {
  constructor(){
    super();
    console.log("App");
  }
  render() {
    return (
      <div>
        <h1>
          <Hello />
          Hello<br />
          <input type="text" name="" id="" />
        </h1>
        <svg className="icon-svg" aria-hidden="true">
          <use xlinkHref="#d-icon-gou-check"></use>
        </svg>
      </div>
    )
  }
}

export default hot(module)(App)

这里的svg可以进行删除


index.jsx

import React from 'react'
import { render } from 'react-dom'
import App from './App.jsx'
import './scss/index.scss';
const root = document.createElement('div')
document.body.appendChild(root)

render(<App />, root)


这里我们可以发现,在index.jsx中是自行创建了一个div所以我们在模版文件中其实可以不用哪个我们经常使用的

<div id=root></div>

子组件

hello.jsx

import React from 'react';
import { hot } from 'react-hot-loader';
export class Hello extends React.Component{
    render(){
        return (
            <div>hello</div>
        )
    }
}


可以发现,我们的子组件并没有使用hot这个东西,代表只要我们给根组件设置hot就好了。

官网上给出的例子是使用--hot进行启动,如果我们只想在webpack中进行配置而不是使用npm script

我们可以这样配置webpack的config文件。

webpack.config.dev.js

console.log("dev");

const path = require('path');
const webpack = require('webpack');
const htmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const HotModuleReplacePlgun = require('webpack/lib/HotModuleReplacementPlugin');
module.exports = {
  entry: ['react-hot-loader/patch', './src/index.jsx'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: 'js/[name].js'
  },
  module: {
    rules: [
      {
        test: /\.jsx$/,
        exclude: /(node_modules)/,
        include: path.resolve(__dirname, 'src'),
        use: {
          loader: "babel-loader",
          options: {
            presets: ['env', 'react'],
            plugins: ['react-hot-loader/babel'],
          }
        }
      },
      {
        test: /\.css$/,
        include: path.resolve(__dirname, 'src'),
        use:[
            "style-loader",
            "css-loader"
        ]
      },
      {
        test: /\.scss$/,
        include: path.resolve(__dirname, 'src'),
        use:[
            "style-loader",
            "css-loader",
            "sass-loader"
        ]
      },
      {
        test: /\.(gif|png|jpg)$/,
        include: path.resolve(__dirname, 'src'),
        use: [{
          loader: "url-loader",
          options: {
            limit: 8192,
            name: "assets/img/[name].[ext]"
          }
        }],
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        include: path.resolve(__dirname, 'src'),
        use: [{
          loader: "url-loader",
          options: {
            limit: 8192,
            name: "assets/[name].[ext]"
          }
        }],
      },
    ]
  },
  plugins: [
    new htmlWebpackPlugin({
      template: "./src/index.html"
    }),
    // new ExtractTextWebpackPlugin("css/[name].css"),
    // new ExtractTextWebpackPlugin("scss/[name].scss"),使用这个就无法开启热模块替换了
    // 提取公共模块 
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common',
      filename: "js/base.js",
    }),
    // 设置热更新
    new HotModuleReplacePlgun(),
    new webpack.NamedModulesPlugin(),
  ],
  devServer: {
    port: 8888,
    // 使用热模块更新,必须安装插件
    hot:true,
    // 自动在启动后打开浏览器
    open : true,
    openPage:'dist/',
  },
  resolve: {
    // 配置寻找第三方库的时候的位置
    modules: [path.resolve(__dirname, 'node_modules')],
    // extensions:['jsx','js','json']
  },
  watchOptions: {
    // 不监听这些文件
    ignored: /node_modules/
  },
  devtool: 'source-map'
};

这里最关键的是

jsx的配置以及入口文件的配置

entry: [ 'react-hot-loader/patch', './src/index.jsx'],


{
test: / \. jsx $ /,
exclude: / ( node_modules ) /,
include: path. resolve( __dirname, 'src'),
use: {
loader: "babel-loader",
options: {
presets: [ 'env', 'react'],
plugins: [ 'react-hot-loader/babel'],
}
}
},



然后设置hot为true

devServer: {
port: 8888,
// 使用热模块更新,必须安装插件
hot: true,
// 自动在启动后打开浏览器
open : true,
openPage: 'dist/',
},



这里要注意的一点是,我们没有使用单独提取文件的功能把css进行单独抽出

const ExtractTextWebpackPlugin = require( 'extract-text-webpack-plugin');


这个原因是因为他不支持热模块更新的原型,一旦单独提取了css文件,那么我们修改了scss跟css都不会立即生效。

所以我们需要两个webpack.config.js文件来实现开发跟生产的区分。

最后是npm的执行文件

"dev": "node_modules \\ .bin \\ webpack-dev-server --config webpack.config.dev.js",


问题得以解决。

因为技术的更新其实很快。可能当你看到这篇博文的时候,里面的方法已经跟最新版的对不上了,这个时候我还是建议你去github上面把这个项目clone下来。然后执行一下里面的例子看看,这个样子应该会好一点。


猜你喜欢

转载自blog.csdn.net/aboyl/article/details/79776904