Webpack 4.x搭建react開發環境

Countbunny發表於2018-08-14

必要依賴一覽(npm install) 安裝好。

"dependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "react": "^16.4.2",
    "react-dom": "^16.4.2",
    "webpack": "^4.16.5"
    ...
}
複製程式碼

babel系列是幹什麼用的呢?是為了支援es6以上的高階語法的編譯。但是因為react有jsx這個東西存在,所以單純的babel是不夠的,此外要讓babel作用於webpack,需要給webpack新增一個loader(以前版本叫loader,4.x版本開始改用‘rules’),在工程根目錄新建webpack.config.js檔案,並新增如下程式碼:

var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var deps = [ 
  ];

//以上程式碼可以忽略,沒有必要不要新增noParse,因為依賴程式碼中可能會有環境的判斷,而瀏覽器中是拿不到process變數的,會報錯!
var config = {
    //這裡是打包的入口
  entry: path.resolve(__dirname, './react/app.js'),
  resolve: {
    alias: {
    }
  },
  //打包完成後輸出到./build/bundle.js檔案中
  output: {
    path: path.resolve(__dirname, './build'),
    filename: 'bundle.js',
  },
  mode: 'development',
  module: {
      //上述的規則,loader就放在這裡,這段沒什麼好說的,從Webpack官方文件上直接拿來用
    rules: [
        {
          test: /\.js$/,
          exclude: /(node_modules|bower_components)/,
          use: {
            loader: 'babel-loader',
            options: {
                //剛剛下載的module之一
              presets: ['babel-preset-env']
            }
          }
        }
      ]
  }
};

//遍歷你的自定義要排除的依賴,安裝到node_modules裡的依賴一般不需要排除掉
deps.forEach(function (dep) {
    var depPath = path.resolve(node_modules, dep);
    config.resolve.alias[dep.split(path.sep)[0]] = depPath;
    config.module.noParse.push(depPath);
  });

module.exports = config;
複製程式碼

以上程式碼可以直接用,請先將註釋去掉。有了以上檔案配置,你可以直接在package.json中新增scripts來打包你的app.js。

...
"scripts": {
    ...
    "build-config": "webpack",
    ...
}
...
複製程式碼

執行npm run build-config可執行打包操作,但是目前為止還是會報錯,因為缺少babel設定,webpack打包時無法識別jsx語法,什麼時jsx語法?就是在js程式碼中寫的類似於dom結構的東西,如下:

...
<h1 onClick={this.handleClick.bind(this)} style={{ color: "red" }}>
    {'Hello ' + this.state.text}
</h1>
...
複製程式碼

要解析這個東西還需要新增.babelrc檔案,在其中新增:

{
    "plugins": ["transform-react-jsx"]
}
複製程式碼

這句主要是說在babel參與打包時,會啟用jsx轉換成js的外掛。到這裡你已經可以成功打出你想要的bundle.js

> webpack

Hash: e716d360a6a752006c09
Version: webpack 4.16.5
Time: 973ms
Built at: 2018-08-14 15:19:14
    Asset     Size  Chunks             Chunk Names
bundle.js  715 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./react/app.js] 2.74 KiB {main} [built]
    + 21 hidden modules
複製程式碼

webpack打包的好處就是這裡,可以讓你的app載入速度更快,如上的包總計715kb,隱藏了沒有用到的模組21個。這就是為什麼要搭手腳架開發的理由。

jsx-transform的坑

此外還有一點要說一下,就是在引入React時,請整個引入,要麼就額外引入它在編譯後的程式碼中可能會用到的api,否則會說什麼什麼沒找到而導致頁面載入不出來。看編譯後的程式碼:

var _react = __webpack_require__(/*! react */ "./node_modules/react/index.js");
var _react2 = _interopRequireDefault(_react);
...
_createClass(MyTitle, [{
key: "handleClick",
value: function handleClick() {
    this.setState({
    text: "Clicked"
    });
}
}, {
key: "render",
value: function render() {
    return _react2.default.createElement(
    "h1",
    { onClick: this.handleClick.bind(this), style: { color: "red" } },
    'Hello ' + this.state.text
    );
}
}]);
複製程式碼

如果你不引入react, 編譯後render()函式中的_react2會是React.createElement而React顯然是找不到這個變數的。看到編譯後的程式碼,你可能更能理解,哦在jsx的dom中那樣寫原來是這個意思啊···

Vscode中開發,需要配置好eslint

react中有大量的es6的寫法,如果不配置eslint你會看到大量飄紅,首先是在專案的開發環境安裝依賴:

"devDependencies": {
    ···
    "eslint": "^5.3.0",
    "eslint-plugin-import": "^2.14.0"
    ···
}
複製程式碼

在專案根路徑下新增.eslintrc.json,並新增以下程式碼[^eslint]:

{
  "parserOptions": {
      //使用的ecma版本
    "ecmaVersion": 6,
    "sourceType": "module",
    //使用jsx特性
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "rules": {
      //忽略console的警告
    "no-console": "off",
    "semi": ["error", "always"]
  }
}
複製程式碼

參考:
eslint官方文件
babel-plugin-transform-jsx文件
webpack4.15.1 官方文件
babelrc 配置文件
React+Webpack快速上手指南(雖然已經過時,還有部分不適用,但是還是借鑑了一部分程式碼)
阮一峰 四課時培訓課,雖然過時,但是還是能帶你體驗一番前端開發

相關文章