前言 css
下面是咱們使用到技術棧:html
webpack + react + redux + react-router + react-thunk + ES6 + ....react
注意事項:webpack
建議使用npm5.X 或者 yarn 包管理工具(最好不要使用cnpm,雖然安裝包速度上很快,可是在文件關聯上會有坑,以前用的時候被坑過)git
1、新建項目目錄github
config : webpack 配置文件web
dist: 打包後代碼npm
src: 源碼目錄json
2、基礎配置redux
安裝基礎的包
// 生成默認package.josn 文件 npm init // 安裝 webpack 和 webpack-dev-server npm install webpack webpack-dev-server --save-dev // 安裝 react react-dom npm install react react-dom --save // 安裝 babel-core 、babel-loader、babel-preset-env、babel-preset-react npm install babel-core babel-loader babel-preset-env babel-preset-react --save-dev // html-webpack-plugin 生成html文件 npm install html-webpack-plugin --sav-dev
添加 webpack 配置
先添加部分基礎文件:
config/webpack/file.path.js
1 const { resolve } = require('path') 2 3 // 項目根目錄 4 const projectPath = process.cwd() 5 // 代碼地址目錄 6 const srcPath = resolve(projectPath, 'src') 7 // 入口文件目錄 8 const mainPath = resolve(srcPath, 'main') 9 10 // 入口文件 11 const indexJsPath = resolve(mainPath, 'index.jsx') 12 const indexHtmlPath = resolve(mainPath, 'index.html') 13 14 module.exports = { 15 srcPath, 16 mainPath, 17 indexJsPath, 18 indexHtmlPath 19 }
config/webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin') const { srcPath, indexJsPath, indexHtmlPath } = require('./file.path.js') // 生成HTML文件 const generateIndex = new HtmlWebpackPlugin({ inject: 'body', filename: 'index.html', template: indexHtmlPath }) module.exports = { // 基礎目錄(絕對路徑),用於從配置中解析入口點和加載程序 // 默認使用當前目錄,但建議在配置中傳遞一個值。這使得您的配置獨立於CWD(當前工做目錄) context: srcPath, // 入口文件 entry: indexJsPath, // 輸入配置 output: { }, // 模塊配置 module: { rules: [ { test: /\.jsx?$/, use: 'babel-loader' } ] }, // 插件配置 plugins: [ generateIndex ] }
添加 babel 配置 .babelrc:
.babelrc
1 { 2 "presets": [ 3 "env", // babel 啓動插件 4 "react" // 編譯react語法插件 5 ] 6 }
添加入口文件 src/main/index.jsx:
1 import React from 'react' 2 import ReactDOM from 'react-dom' 3 4 const render = () => { 5 ReactDOM.render( 6 <h1>Hello React</h1>, 7 document.getElementById('app-container') 8 ) 9 } 10 11 render()
添加 index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>webpack react配置</title> 8 </head> 9 <body> 10 11 </body> 12 </html>
在package.json 中添加啓動命令:
{ ... "scripts": { "start": "webpack-dev-server --config config/webpack.config.js" }, ... }
如今能夠直接在cmd中運行:
npm run start
能夠在瀏覽器打開 http://localhost:8080/ ,你能夠看到一下效果:
完整代碼地址:https://github.com/haozhaohang/library/tree/master/webpack%20react%E9%85%8D%E7%BD%AE/lessons%201
3、高級配置
1. 添加 react-router
// 安裝 react-router-dom npm install react-router-dom --save
添加 src/main/app.js
1 import React, { Component } from 'react' 2 import { BrowserRouter, Route, Link } from 'react-router-dom' 3 4 import Home from '../containers/Home' 5 import About from '../containers/About' 6 import Topics from '../containers/Topics' 7 8 // BrowserRouter 下只能有一個子元素 9 class App extends Component { 10 render() { 11 return ( 12 <BrowserRouter> 13 <div> 14 <ul> 15 <li><Link to="/">Home</Link></li> 16 <li><Link to="/about">About</Link></li> 17 <li><Link to="/topics">Topics</Link></li> 18 </ul> 19 20 <hr/> 21 22 <Route exact path="/" component={Home}/> 23 <Route path="/about" component={About}/> 24 <Route path="/topics" component={Topics}/> 25 </div> 26 </BrowserRouter> 27 ) 28 } 29 } 30 31 export default App
添加 containers/Home/index.js
1 import React, { Component } from 'react' 2 3 const Home = () => { 4 return ( 5 <div> 6 Home 7 </div> 8 ); 9 } 10 export default Home
添加 containers/About/index.js
1 import React from 'react' 2 3 const About = () => ( 4 <div> 5 about 6 </div> 7 ) 8 9 export default About
添加 containers/Topics/index.js
import React from 'react' const Topics = () => { return ( <div> topics </div> ); } export default Topics
修改 src/main/index.jsx 文件
1 import React from 'react' 2 import ReactDOM from 'react-dom' 3 4 import App from './app.js' 5 6 const render = Component => { 7 ReactDOM.render( 8 <Component />, 9 document.getElementById('app-container') 10 ) 11 } 12 13 render(App)
路由咱們添加完了,能夠運行項目, 在瀏覽器 http://localhost:8080/ 預覽效果。
react-router路由有 BrowserRouter和HashRouter 兩種路由,二者的區別:
BrowserRouter 使用HTML5 歷史API, HashRouter 使用哈希值
例如:若是同一個修改用戶信息路由,在BroserRouter下顯示 user/edit,而在HashRouter 下顯示爲 #/user/edit
刷新頁面BrowserRouter會向服務端發送請求,後臺要作必定處理,而HashRouter 不會向服務端發送請求
在react-router 4.0 的文檔中有這樣一段話:
注意: 使用 hash 的方式記錄導航歷史不支持 location.key 和 location.state。 在之前的版本中,咱們爲這種行爲提供了 shim,可是仍有一些問題咱們沒法解決。 任何依賴此行爲的代碼或插件都將沒法正常使用。 因爲該技術僅用於支持傳統的瀏覽器,所以在用於瀏覽器時可使用 <BrowserHistory> 代替。
完整代碼地址:https://github.com/haozhaohang/library/tree/master/webpack%20react%E9%85%8D%E7%BD%AE/lessons2
2.配置redux 、react-thunk
// 安裝redux react-redux npm install redux react-redux react-thunk --save
添加 src/main/store.js
1 import { combineReducers, createStore, applyMiddleware } from 'redux' 2 import thunk from 'redux-thunk' 3 4 import rootReducers from '../reducers' 5 6 const middleware = [thunk] 7 8 const store = createStore( 9 combineReducers(rootReducers), 10 {}, 11 applyMiddleware(...middleware) 12 ) 13 14 export default store
添加 src/reduxcers/index.js
1 function userInfo(state = {}) { 2 return { 3 name: 'react' 4 } 5 } 6 7 export default { 8 userInfo 9 }
修改 src/main/app.js
1 import { Provider } from 'react-redux' 2 import store from './store' 3 4 ... 5 6 render() { 7 return ( 8 <Provider store={store}> 9 ... 10 </Provider> 11 ) 12 } 13 14 ...
修改 src/tontainers/Home/index.js
1 import React, { Component } from 'react' 2 import { connect } from 'react-redux' 3 4 const Home = ({ userInfo }) => { 5 return ( 6 <div> 7 Home 8 <div> 9 這是redux中的數據 10 {userInfo.name} 11 </div> 12 </div> 13 ); 14 } 15 16 const mapStateToProps = ({ userInfo }) => { 17 return { 18 userInfo 19 } 20 } 21 22 const mapDispatchTopProps = {} 23 // 使用connect 關聯redux 24 export default connect(mapStateToProps, mapDispatchTopProps)(Home)
redux咱們添加完了,能夠運行項目, 在瀏覽器 http://localhost:8080/ 預覽效果。
完整代碼地址:https://github.com/haozhaohang/library/tree/master/webpack%20react%E9%85%8D%E7%BD%AE/lessons3
3.配置 react 熱加載
修改 config/webpack.config.js
1 const webpack = require('webpack') 2 3 ... 4 5 // 插件配置 6 plugins: [ 7 ... 8 // 開啓全局的模塊熱替換(HMR) 9 new webpack.HotModuleReplacementPlugin(), 10 // 熱加載中能夠輸入更加友好的模塊名 11 new webpack.NamedModulesPlugin() 12 ] 13 14 ... 15 16 devServer: { 17 hot: true 18 } 19 ...
這樣配置已經能夠實現熱加載了,可是並不算結束,還須要配置 react-hot-loader 的熱加載插件,這是由於 webpack-dev-server只能即時的刷新頁面,可是組件中的狀態保存不住,由於React有一些本身的語法(jsx)是HotModuleReplacementPlugin處理不了。而react-hot-loader 在 --hot 基礎上作了額外的處理,來保證狀態能夠存下來。
// 安裝 react-hot-loader npm install react-hot-loader --save
修改 .babelrc
{ "presets": [ ["env", { "modules": false }], "react" ], "plugins": ["react-hot-loader/babel"] }
添加 react-hot-loader/patch 和 publicPath 到 webpack.config.js,
1 ... 2 3 module.exports = { 4 ... 5 // 入口文件 6 entry: [ 7 'react-hot-loader/patch', 8 indexJsPath 9 ], 10 11 // 輸入配置 12 output: { 13 publicPath: '/' 14 }, 15 16 ... 17 } 18 19 ...
修改 src/main/index.jsx
import React from 'react' import ReactDOM from 'react-dom' import { AppContainer } from 'react-hot-loader' import App from './app.js' const render = Component => { ReactDOM.render( <AppContainer> <Component /> </AppContainer>, document.getElementById('root'), ) } render(App) // Webpack Hot Module Replacement API if (module.hot) { module.hot.accept('./containers/App', () => { render(App) }) }
react-hot-loader 就配置完成了,如今更改三個頁面中的文件,就能夠在頁面中實時看到。
配置時注意事項:
react-hot-loader咱們添加完了,能夠運行項目, 在瀏覽器 http://localhost:8080/ 預覽效果。
完整代碼地址:https://github.com/haozhaohang/library/tree/master/webpack%20react%E9%85%8D%E7%BD%AE/lessons4
4. 配置各類資源的loader
css資源加載器
// 安裝 style-loader css-loader postcss-loader npm install style-loader css-loader postcss-loader --save-dev
下面是webpack.config.js 中的配置
1 ... 2 // 模塊配置 3 module: { 4 rules: [ 5 ... 6 { 7 test: /\.css$/, 8 use: [ 9 { 10 loader: 'style-loader' 11 }, 12 { 13 loader: 'css-loader', 14 options: { 15 importLoaders: 1 16 } 17 }, 18 { 19 loader: 'postcss-loader' 20 } 21 ] 22 } 23 ... 24 ] 25 }, 26 ...
使用postcss須要添加postcss.config.js
module.exports = { plugins: [ // 添加你須要的插件,這個後面會提到 ] }
以前一直使用sass,可是這裏並無選擇sass、less等css預處理框架,我的認爲postcss是一個平臺,提供了豐富的插件,能夠更好處理css。
圖片資源的加載
// 安裝 url-loader file-loader npm install url-loader file-loader --save-dev
下面是webpack.config.js 中的配置
1 ... 2 // 模塊配置 3 module: { 4 rules: [ 5 ... 6 { 7 test: /\.(png|jpg|gif)$/, 8 use: [ 9 { 10 loader: 'url-loader', 11 options: { 12 limit: 8192 13 } 14 } 15 ] 16 }, 17 ... 18 ] 19 }, 20 ...
url-loader: 能夠將圖片小於8192(根據limit設置而定)的圖片裝成base64和源碼添加在一塊兒,減小請求,提升加載速度。
file-loader: 對url-loader沒法處理的圖片資源(大於limit設置的值),使用此loader進行處理,固然這個loader還能夠加載字體圖標等文件,這裏就不在詳細添加了。
完整代碼地址:https://github.com/haozhaohang/library/tree/master/webpack%20react%E9%85%8D%E7%BD%AE/lessons5
基本的配置都講完了,後續系列中會講到優化webpack配置、開發生成配置的拆分、構建優化和服務代理,mock數據等功能
若是本文對你有幫助,請給個 star,感謝^_^