react 熱替換 ([HMR])


react 熱替換 ([HMR])

熱替換好多地方可以用到,目前比較流行的用法是搭配React和webpack實現在不刷新頁面的情況下對模塊的增刪改。在給項目添加熱替換功能的時候,可以說是踩了各種坑,webpack官方給的配置也有小問題還不得不翻牆去解決(百度出來的一個能打的也沒有)。
官方的方案在這兒:https://webpack.js.org/guides/hmr-react/
我先把自己配置成功的貼出來,再說一下如果完全照搬官方配置,會產生的問題:
(只保留熱替換相關配置和最基礎配置,且只考慮開發不考慮生產,且假設你已安裝必要的包)

module.exports = {
  entry: [
    'react-hot-loader/patch', // 1
    // 開啟 React 代碼的模塊熱替換(HMR)
    './src',
  ],
  output: {
    filename: 'js/bundle.js',
    path: path.resolve(__dirname, 'public'),
    publicPath:'http://localhost:7000/', // 2
  },
  module: {
    rules: [
      { test: /\.(js|jsx)$/, use: 'babel-loader', exclude: /node_modules/ },
      { test: /\.css$/,
        use:['style-loader', 'css-loader', 'postcss-loader'], // 3
        exclude: /node_modules/ },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  devServer: {
    port: 7000,
    hot: true, // 4
    // 開啟服務器的模塊熱替換(HMR)
    headers: {
      'Access-Control-Allow-Origin': '*', // 5
    },
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), // 6
    // 開啟全局的模塊熱替換(HMR)

    new webpack.NamedModulesPlugin(), // +
    // 當模塊熱替換(HMR)時在瀏覽器控制台輸出對用戶更友好的模塊名字信息
  ],
}

react 和babel 部分的配置與官方相同即可。
參考官方配置你遇到第一個問題:

[HMR] Update failed: SyntaxError: Unexpected token < in JSON at position 0
    at Object.parse (<anonymous>)
    at XMLHttpRequest.request.onreadystatechange

這個問題很頭疼,因為你去搜索完全找不到有用的東西,而且你看不出來錯在哪了,當時的心情真是。。。
最后在 react-hot-loader 的 github 庫的 Issues 里翻到了有人和我一樣的問題,大快人心。
原來是 output 的 publicPath 出了問題用 '/' 是不行滴,要把啟動webpack服務的地址填上:'http://localhost:7000/'。其實也不能怪官方文檔,人家是假設你應用程序和包都托管給 webpack 服務,但是我的只把包托給了 webpack 服務,應用程序是另外啟動的 node 服務。好吧這是個比較小眾的問題,你要是正好有這個問題,還搜到了這篇文章,那是好福氣了。
另外一個

XMLHttpRequest cannot load http://localhost:7000/4221731a75de7a449377.hot-update.json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 404

這個問題只在 webpack 服務發生變動時候有,並不影響HMR使用,所以不管它也可以。
devServer里添加

 headers: {
      'Access-Control-Allow-Origin': '*', // 5
    },

即可,也是因為應用程序沒有托管給 webpack 導致。
如果你的應用程序和包都是托管給 webpack 服務,那就沒有這兩個問題了。
(話說應用程序一般都是另啟服務的吧。。。)
再說一個問題,除了上面兩個,是不是這么多配置都是必須的。不配置會導致什么錯誤。
首先,

entry里的
'react-hot-loader/patch', // 1
devServer里的
hot: true, // 4
plugins里的
new webpack.HotModuleReplacementPlugin(), // 6

從字面上看就是必須的,不用想,否則不會熱。
new webpack.NamedModulesPlugin(), // +只是讓控制台輸出的更友好,推薦但非必需
這個比較容易忽略:

      { test: /\.css$/,
        use:['style-loader', 'css-loader', 'postcss-loader'], // 3
        exclude: /node_modules/ },

style-loader 是必須的,否則樣式的刷新就不熱了。
很多人用 ExtractTextWebpackPlugin 把 css 文件單獨弄出來就不用 style-loader了,不過推薦部署應用之前弄一份就行,開發用不着 ExtractTextWebpackPlugin 。
不用 style-loader 修改樣式表就不會無刷新更新頁面了。不過這一點容易想到。
還有一點就是 babel 配置文件里禁用 modules 很重要,否則導致各種問題,根本別想愉快的開發。這個對應用程序本身使用 import 沒有影響,畢竟 webpack2 啥標准都支持,其他地方就用 require 吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM