react-hot-loader 實測

久未回 js 的懷抱,真沒想到1年半的空白會產生這麼多的問題

一開始只是很單純的想找回 js 的手感,並來練一下 react,沒想到處處是坑

最大的問題在,前端的開發套件百家爭鳴外,版本也是個很大的問題

尤其以版本不相容,造成找到的資料不適用,不然就是噴錯也是噴的我一頭霧水

抱怨到此,來說說我遇到的狀況吧


一開始想練習 react ,便著手開始做開發環境的搭設

  1. 安裝 webpack、webpack-dev-server
    1
    2
    3
    4
    {
    "webpack": "^2.3.2",
    "webpack-dev-server": "^2.4.2"
    }
  1. 安裝 babel

    1
    2
    3
    4
    5
    6
    {
    "babel-core": "^6.24.0",
    "babel-loader": "^6.4.1",
    "babel-preset-es2015": "^6.24.0",
    "babel-preset-react": "^6.23.0",
    }
  2. 開始建立 webpack.config.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
    var webpack = require("webpack");
    var path = require('path');
    var cfg = {};
    cfg.entry = path.resolve(__dirname,'./src/App.js');
    cfg.devtool = "source-map";
    cfg.output = {
    path : path.resolve(__dirname, "dist"),
    filename : "bundle.js"
    };
    cfg.devServer = {
    contentBase: path.join(__dirname, "."),
    compress: true,
    hot:true,
    port: 9000
    }
    cfg.externals = {
    'react': 'React',
    'reactdom': 'ReactDOM'
    };
    var plugins = [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
    ];
    cfg.plugins = plugins;
    var rules = [
    {
    test: /\.js?$/,
    exclude: /(node_modules|bower_components)/,
    loader:'babel-loader'
    }
    ];
    cfg.module = {
    rules
    }
    module.exports = cfg;

以上就把開發環境搞定,練習的過程中,對不停的 reload page開始厭煩
便裝了 react-hot-loader,本以為裝了就上!! 沒想到問題還是一堆

撞牆的過程,就不說了
主要的原因為

react-hot-loader 有分 1.x 版跟 3.x beat 版
一開始的專案,我所用的是 external 的 react ,也就是由 cdn 上抓下來的

react-hot-loader 1.x 版的並不支援此方法
必需要把 react 包進 project 中才行
而設定方法

  • 修改 webpack.config.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //修改 entry
    cfg.entry = [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    path.resolve(__dirname,'./src/App.js')
    ]
    //拿掉外部 React
    // cfg.externals = {
    // 'react': 'React',
    // 'reactdom': 'ReactDOM'
    // };
    //修改 loader
    var rules = [
    {
    test: /\.js?$/,
    exclude: /(node_modules|bower_components)/,
    loaders: ['react-hot-loader', 'babel-loader']
    }
    ];

以上再重啟專案
應該就可以了

重點

  1. react-hot-loader 要是 1.x 版
  2. React 必需要是 internal lib
  3. webpack 需要做相關的設定修改

網路上有人會 建立

  • server.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var webpack = require('webpack');
    var WebpackDevServer = require('webpack-dev-server');
    var config = require('./webpack.config');
    new WebpackDevServer(webpack(config), {
    publicPath: config.output.publicPath,
    hot: true,
    historyApiFallback: true
    }).listen(3000, 'localhost', function (err, result) {
    if (err) {
    console.log(err);
    }
    console.log('Listening at localhost:3000');
    });

再用

1
node server.js

來啟動 webpack-dev-server
但我自已習慣是直接用

1
2
dev:"webpack-dev-server
npm run dev

來啟動 wds

ok 再來談談 react-hot-loader 3.xBeta 版
因為本人莫名的堅持,非要把 React 拉出去不可
故參考這篇
https://github.com/gaearon/react-hot-loader/blob/master/docs/README.md#usage-with-external-react

so Let’s go

  1. 先安裝好 3.x 的 react-hot-loader

    1
    npm i react-hot-loader@next
  2. 修改 webpack.config.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //entry 改成
    cfg.entry = [
    'react-hot-loader/patch',
    path.resolve(__dirname,'./src/App.js')
    ];
    cfg.externals = {
    'react': 'React',
    'reactdom': 'ReactDOM'
    };
    var rules = [
    {
    test: /\.js?$/,
    exclude: /(node_modules|bower_components)/,
    loader:'babel-loader'
    }
    ];
  3. 修改 .babelrc

    1
    2
    3
    4
    5
    6
    {
    "presets": [
    "es2015", "react"
    ],
    "plugins": ["react-hot-loader/babel"]
    }
  4. 修改 entry file
    我原本的 entry file 是
    App.js

    1
    2
    3
    4
    import {render} from "reactdom";
    import Comp from './view/Comp';
    render( <Comp/>, document.getElementById('app'));

    修改為

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import {render} from "reactdom";
    import Comp from './view/Comp';
    import { AppContainer } from 'react-hot-loader'
    render( <AppContainer>
    <Comp/>
    </AppContainer>, document.getElementById('app'));
    // Hot Module Replacement API
    if (module.hot) {
    module.hot.accept('./view/Comp', () => {
    const NextApp = require('./view/Comp').default;
    render(
    <AppContainer>
    <NextApp/>
    </AppContainer>,
    document.getElementById('app')
    );
    });
    }

ok 一樣重點匯整

  1. react-hot-loader 要是 3.x 版
  2. React 必需要是 external lib
  3. webpack 需要做相關的設定修改
  4. .babelrc 要加入 plugin 的設定
  5. 修改 entry file 的 root comp….(WTF!!)

要注意的是第5點,這個是直接動到 code
可能是要分成

  • App.hot.js
  • App.js

並用 webpack.config.js 來設定要用那個 entry file
我看非常有可能一不小心就包錯檔…

搞完這麼大一串,不禁讓我自已開始思考
前端還有多少個坑要踩…..