React項目構建(利用webpack打包)

引言

  最近React做爲當前最爲火熱的前端框架。最近也相繼而出來相關ES7的新語法。html

  固然,在使用React開發web項目的時候,不得不提到的就是與之配套的相應的打包技術,以前上文已經簡單的提到React+webpack的相關環境搭建。前端

  不過昨天,在技術羣聊裏,又有人提到,如何更好的利用webpack進行開發與打包。那麼今天,我就用一個例子來解釋一下,利用webpack來打包react項目與發佈的相關配置(包含Request請求和React-router的路由跳轉哦)。node

準備工做

  固然須要安裝WebStrom和node.js啦~至於下載地址,請看上文:React+Webpack+ES6環境搭建(自定義框架)react

讓咱們跑起來吧

  首先來講說,本項目基本用到的一些開發組件(package.json):webpack

  1. 開發中須要用到的,我所有放在devDependencies(npm install ...... --save-dev)中;
  2. 項目中有用到的組件,我所有放在dependencies(npm install ...... --save)中;
"devDependencies": {
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.8",
    "babel-polyfill": "^6.16.0",
    "babel-preset-latest": "^6.16.0",
    "babel-preset-react": "^6.16.0",
    "open": "0.0.5",
    "react-hot-loader": "^3.0.0-beta.6",
    "webpack": "^1.13.3",
    "webpack-dev-server": "^1.16.2"
  },
  "dependencies": {
    "echarts": "^3.3.1",
    "isomorphic-fetch": "^2.2.1",
    "lodash": "^4.17.2",
    "react": "^15.4.0",
    "react-dom": "^15.4.0",
    "react-router": "^3.0.0"
  }

  接下來,就是server.js的配置,利用於調試以及用戶服務端口配置git

/**
 * 建立時間:2016年9月19日 10:12:44
 * 建立人:JaminHuang
 * 描述:用於服務端口配置
 */
'use strict';
var open = require('open');
var webpack =require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config.js');

var compiler = webpack(config);
var server = new WebpackDevServer(compiler, {
    publicPath:config.output.publicPath,
    hot:true,
    historyApiFallback: true,
    quiet: false,
    noInfo: false,
    filename: "index.js",
    watchOptions: {
        aggregateTimeout: 300,
        poll: 1000
    },
    headers: {"X-Custom-Header": "yes"},
    stats: {colors: true}
});

server.listen(3010, function (err, result) {
    if (err)console.log(err);
    open('http://localhost:3010');
});
server.js

  配置完成後,而且在創建index.js的主入口文件後(具體怎麼創建,請看前文環境搭建,這裏就不重複講了)。下面就是核心,webpack.config.js的配置啦。不過這裏項目用引用了熱加載(react-hot-loader),而該組件在更新版本3.0.0以後,有一些小坑,須要修復,下文會提到。github

  首先,能夠配置調試文件(webpack.config.js)和發佈配置文件(webpack.production.config.js)web

'use strict';
var path = require('path');
var webpack = require('webpack');

var config = {
    devtool: 'source-map',
    entry: {
        app: ['webpack-dev-server/client?http://localhost:3010', 'webpack/hot/dev-server', './src/index']
    },
    output: {
        path: path.join(__dirname, 'public'),
        publicPath: '/public/',
        //chunkFilename: '[id].chunk.js',
        filename: "bundle.js"
    },
    module: {
        loaders: [
                {test: /\.js$/, loader: 'babel', include: path.join(__dirname, 'src')}
            ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        //new webpack.optimize.CommonsChunkPlugin('shared.js'),
        new webpack.DefinePlugin({
            'process.env': {
                'DEBUG': true
            }
        })
    ]
};
module.exports = config;
webpack.config.js
'use strict';
var path = require('path');
var webpack = require('webpack');

module.exports = {
    devtool: false,
    debug: false,
    stats: {
        colors: true,
        reasons: false
    },
    entry: './src/index',
    output: {
        path: path.join(__dirname, 'public'),
        publicPath: '/public/',
        //chunkFilename: '[id].chunk.js',
        filename: 'bundle.js'
    },
    plugins: [
        new webpack.optimize.DedupePlugin(),
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production'),
                'DEBUG': false
            }
        }),
        //new webpack.optimize.CommonsChunkPlugin('shared.js'),
        new webpack.optimize.UglifyJsPlugin({
            compressor: {
                warnings: false
            }
        }),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.optimize.AggressiveMergingPlugin(),
        new webpack.NoErrorsPlugin()
    ],
    module: {
        loaders: [
            {test: /\.js$/, loader: "babel", exclude: /node_modules/}
        ]
    }
};
webpack.production.config

  因爲調試文件中,引用了熱加載的問題,因此這裏也提一下上面以前遇到的坑。因爲3.0.0版本的react-hot-loader,對於webpack中配置的有些loaders語法不識別,npm

  以前版本的寫法:json

module: {
        loaders: [
            {test: /\.js$/, loaders: ['react-hot', 'babel'], include: [path.join(__dirname, 'src')]}
        ]
    },

  調整以後的寫法,別寫須要在以前配置的.babelrc文件中添加一行配置(固然能夠寫進):

{
  "plugins": ["react-hot-loader/babel"]
}

  webpack.config中的配置

module: {
        loaders: [
                {test: /\.js$/, loader: 'babel', include: path.join(__dirname, 'src')}
            ]
    },

  最後,在package.json中配置命令,方便執行就好了:

"scripts": {
    "start": "node server.js",
    "prod": "webpack --config webpack.production.config.js"
  },

  這樣一些都配置完成了,如須要調試則輸入"npm start"就行,如須要發佈就能夠輸入"npm prod"便可

有關發佈

  這裏在說一下,若是想要發佈項目的時候,在輸入"npm prod"以後,(以前根據webpack已經配置好了目錄)只須要到項目跟目錄下把public文件夾和index.html拷出來(由於這裏舉例的webpack發佈配置,我並無將index.html也打包進入public文件夾,因此須要多打包一下)

  拷出來後,則能夠經過IIS進行項目發佈啦。(不過若是利用IIS的話,須要添加URL重寫工具)以及在發佈的根目錄下配置web.config文件,配置URL重寫。

 

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.webServer>
        <!-- todo: 也許應該過濾掉靜態文件 -->
        <rewrite>
            <rules>
                <rule name="Main Rule" stopProcessing="true">
                      <match url="^(?:(?!api).)+" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

擴展內容

  這裏再,說一些相關擴展的內容:Request請求處理。本項目中利用了一些isomorphic-fetch組件用於幫助請求,項目中我配置了一個公共請求組件:

'use strict';
import fetch from 'isomorphic-fetch';
const baseUrl = "http://xxx";

export function FetchPost(url, data) {
    return fetch(`${baseUrl}/${url}`, {
        headers: {"Content-Type": "application/json"},
        method: 'POST',
        body: JSON.stringify(data)
    }).then(response=> {
        return response.json();
    })
}

  調用方式:

Request.FetchPost("api/Gather/Sign", data).then(json=>{
       if (條件 ) {
                //成功執行....
       }
       else {
                //失敗執行....
       }
})

 附錄

  最後附上個人GitHub上該項目的Demo,若是有須要能夠down下來實際操做一下,固然,請別忘記給個Star哈~內容中有分支,一個是項目搭建,一個是百度EChart的Demo,本文例子用master這個分支就可。

  https://github.com/JaminHuang/EChartDemo

相關文章
相關標籤/搜索