前面咱們已經搭建了基礎環境,如今將開發環境更完善一些。css
在開發的過程,咱們會常常調試,so,爲了方便咱們在chrome中調試源代碼,須要更改webpack.config.js,而後啓動webpack-dev-server。完成以後在chrome瀏覽器中打開debug,點擊Sources選項,便可看見提示,繼而輸入你想查看的源文件名便可顯示該文件源代碼,若是你以爲某處代碼有問題,對應行號打上斷點便可調試。html
...... module.exports = { devtool: 'cheap-module-eval-source-map', ...... }
HMR應該是webpack使人很是興奮的一個特色,它在代碼修改後從新打包併發送到瀏覽器,瀏覽器將獲取的新模塊替換老模塊,在不刷新瀏覽器的狀況下實現對應用的更新。因爲咱們使用的是webpack-dev-server,它提供了兩種自動刷新方式供咱們選擇,iframe和inline模式。這裏咱們選擇inline模式,更改dev-server.js。node
......
const server = new WebpackDevServer(compiler, { contentBase: path.resolve(__dirname, '../build'), // 默認會以根文件夾提供本地服務器,這裏指定文件夾 inline: true, // 自動刷新 hot: true, // 開啓熱模塊替換
......
更改webpack.config.jsreact
......
const webpack = require('webpack');
module.exports = { devtool: 'cheap-module-eval-source-map', entry: [
'webpack-dev-server/client?http://localhost:9090', 'webpack/hot/only-dev-server', path.resolve(__dirname, '../src/index.js') ],
...... plugins: [ new webpack.HotModuleReplacementPlugin()
...... ]
最後更改index.jswebpack
import React from 'react'; import { render } from 'react-dom'; import App from './App' const renderDom = Component => { render( <Component />, document.getElementById('app') ); } renderDom(App); if (module.hot) { module.hot.accept('./App', () => { const App = require('./App').default; renderDom(App); }) }
接下來執行npm run dev,查看瀏覽器,發現以下就實現了熱更新。es6
而後修改App.js裏render返回的html,保存後能夠發現瀏覽器會自動刷新並看到你更改後的效果。也許這樣就實現了React組件的熱更新,Right ?咱們對App.js作以下更改看看會有什麼變化。web
import React, { Component } from 'react'; export default class App extends Component { constructor(props) { super(props); this.state = { count: 1, } } add () { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={() => this.add()}>增長1</button> </div> ); } }
而後在瀏覽器中點擊按鈕,頁面中數值隨之增長。而後,咱們修改一下App.js(在button標籤下增長其餘標籤),保存後瀏覽器自動刷新。咱們查看一下瀏覽器,那麼問題來了,剛剛點擊增長後的數值不見了,又回到了初始值1。這時候發現組件的狀態並無保存下來,沒有達到真正意義上的React熱更新。因此這裏還須要引入一個插件,來幫咱們解決熱更新組件狀態保存問題。這也是react-hot-loader的由來。chrome
npm install react-hot-loader --save-dev npm install babel-polyfill --save
更改webpack.config.js。npm
......
module.exports = { devtool: 'cheap-module-eval-source-map', entry: [ 'babel-polyfill', 'react-hot-loader/patch', 'webpack-dev-server/client?http://localhost:8080', 'webpack/hot/only-dev-server',
......
更改index.js。json
......
import { AppContainer } from 'react-hot-loader'; import 'babel-polyfill'; import App from './App'; const renderDom = Component => { render( <AppContainer> <Component /> </AppContainer>, document.getElementById('app') ); };
......
更改.babelrc。
{ "presets": [ [ "es2015", { "module": false } ], "react" ], "plugins": [ "react-hot-loader/babel"] }
修改完後,須要從新執行npm run dev。咱們重複上面的操做,能夠發現,沒有再出現上面的問題。固然上面的React函數綁定還有多種寫法:
//方式一 <button onClick={() => this.add()}>增長1</button> //方式二 <button onClick={this.add.bind(this)}>增長1</button> //方式三,官方推薦使用 constructor(props) { super(props) this.add = this.add.bind(this); } <button onClick={this.add)}>增長1</button> //方式四,推薦(因爲處於草案階段,因此是以插件的方式使用)
add = () => {
......
} <button onClick={this.add)}>增長1</button>
我更傾向於第四種,更簡潔。這裏咱們配置一下第四種方式。
npm install babel-preset-stage-1 --save
最後修改.babelrc便可。
......
"react", "stage-1"
......
一個JavaScript語法檢測工具,能夠像IDE同樣靜態檢測代碼錯誤並提示。首先安裝eslint和eslint-loader。
npm install eslint eslint-loader --save-dev
修改webpack.config.js。
......
module: { rules: [ { enforce: "pre", test: /\.(js|jsx)$/, loader: 'eslint-loader', exclude: /node_modules/ },
......
項目根目錄下新建.eslintrc.json。
{ "rules": { } }
咱們先不建立規則,直接運行會報error Parsing error: The keyword 'import' is reserved,由於項目中使用了es6等新語法,而這些還不能被直接識別,因此還需安裝babel-eslint進行轉義。
npm install babel-eslint --save-dev
修改.eslintrc.json文件。
{ "parser": "babel-eslint", "rules": { } }
上述修改完後,就能夠從新運行了。到這裏,咱們能夠開始自定義規則,你能夠將本身的規則開源出來供你們一塊兒使用。然而要從頭至尾所有自定義規則並不切合實際,所幸已經有不少符合最佳實踐的規則。這裏咱們選擇Airbnb,安裝eslint-config-airbnb(推薦)。
npm install eslint-config-airbnb --save-dev
eslint-config-airbnb須要下面3個插件的支持:
npm install eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react --save-dev
修改.eslintrc.json,暫時加入如下規則。
{ "parser": "babel-eslint", "extends": "airbnb", "env": { "browser": true, "node": true, "es6": true }, "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { "jsx": true } }, "plugins": [ "react" ], "rules": { "react/jsx-no-bind": [ "error", { "ignoreRefs": true, "allowArrowFunctions": true, "allowBind": true } ], "import/no-extraneous-dependencies": "off", "react/jsx-filename-extension": "off" } }
配置好後從新運行,發現紅了一片(不少錯)。別急,咱們一步一步修改。首先修改index.js,在文件頭部加上/*eslint-disable*/,不對index.js進行校驗。剩餘的咱們就不一一更改了,可讓IDE(Webstorm)爲咱們修改。選擇WebStorm的Preferences,搜索ESLint,將咱們建立的規則應用到項目中。
而後在報錯的文件中,點擊紅色感嘆號,點擊第一項,便可自動修改錯誤。
其餘經常使用加載器還有不少,這裏簡單將css配置了一下,其他就不一一配置介紹了,請自行按需配置。最後webpack.config.js配置以下。
css-loader: 解析css代碼
style-laoder: 將編譯後css樣式導入到html中
less-loader: 加載和轉移less文件
raw-loader: 加載文件原始內容(utf-8格式)
url-loader: 多用於加載圖片
file-loader: 打包文件
const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { devtool: 'cheap-module-eval-source-map', entry: [ 'babel-polyfill', 'react-hot-loader/patch', 'webpack-dev-server/client?http://localhost:9090', 'webpack/hot/only-dev-server', path.resolve(__dirname, '../src/index.js'), ], // 指定入口文件,程序從這裏開始編譯,__dirname當前目錄, ../表示上一級目錄, ./同級目錄 output: { path: path.resolve(__dirname, '../dist'), // 輸出的路徑 filename: 'app/[name]_[hash:8].js', // 打包後文件 }, module: { rules: [ { enforce: 'pre', test: /\.(js|jsx)$/, loader: 'eslint-loader', exclude: /node_modules/, }, { test: /\.(js|jsx)$/, loader: 'babel-loader', // 加載器 exclude: /node_modules/, }, { test: /\.css$/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }], }, { test: /\.less$/, use: [{ loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'less-loader', options: { sourceMap: true, }, }], }, ], }, plugins: [ new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../src/index.template.html'), inject: true, }), ], };