webpack構建react項目(一)

前言 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 就配置完成了,如今更改三個頁面中的文件,就能夠在頁面中實時看到。

配置時注意事項:

  1. 必須將webpack配置中output下publicPath設置爲"/",不然沒法實現熱加載
  2. 將.babelre 中設置babel env預設更改成不使用Babel轉換成ES2015模塊 [ "env": { "modules": false } ]
  3. react-hot-loader在webpack-dev-server的熱加載基礎上作了額外的處理,因此必需要打開webpack-dev-server的 hot模式 才能夠實現熱加載

 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,感謝^_^

相關文章
相關標籤/搜索