Webpack+React+ES6入門指南[轉]

React無疑是今年最火的前端框架,github上的star直逼30,000,基於React的React Native的star也直逼20,000。有了React,組件化彷佛再也不步履蹣跚,有了React Native,前端的邊界彷佛廣闊無邊。而Webpack憑藉它異步加載和可分離打包等優秀的特性,走在取代Grunt和Gulp的路上。而面向將來的ES6,模塊化的支持彷佛已成定局。css

咱們如今就能夠打造本身的Webpack+React+ES6環境而且開始探索起來。html

這篇文章就給還沒走在這條路上的前端一個入門的指南。前端

文章導讀:node

 

1、先把例子跑起來(setup your background)

能夠fork我在github上的[react-webpack]demo項目,也能夠從頭開始:react

1.1 咱們在名爲react-webpack的新項目中要作的第一件事,就是新建一個package.json文件,它看起來應該是這個樣子的:webpack

{
  "name": "react-webpack",
  "version": "1.0.0",
  "description": "webpack demo",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --hot --progress --colors",
    "build": "webpack --progress --colors"
  },
  "repository": {
    "type": "git",
    "url": ".."
  },
  "keywords": [
    "react",
    "webpack"
  ],
  "author": "yixuan",
  "devDependencies": {
    "babel-core": "^5.8.25",
    "babel-loader": "^5.3.2",
    "css-loader": "^0.12.1",
    "react": "^0.13.3",
    "react-hot-loader": "^1.3.0",
    "react-router": "^0.13.3",
    "webpack": "^1.12.2",
    "webpack-dev-server": "^1.11.0"
  },
  "dependencies": {
    "lodash": "~3.10.1",
    "react-kendo": "~0.13.11"
  }
}

1.2 第二步就是建立咱們webpack的配置文件webpack.config.js:git

var webpack = require('webpack');
 module.exports = {
     entry: [
       'webpack/hot/only-dev-server',
       "./js/app.js"
     ],
     output: {
         path: './build',
         filename: "bundle.js"
     },
     module: {
         loaders: [
             { test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
             { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
             { test: /\.css$/, loader: "style!css" }
         ]
     },
     resolve:{
         extensions:['','.js','.json']
     },
     plugins: [
new webpack.NoErrorsPlugin()
     ]
 };

 

1.3 同時咱們還須要在入口文件index.html中引入程序跑起來的一些必要的東西,雖然他的做用看起來沒有那麼明顯:github

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>New React App</title>
    <link rel="stylesheet" type="text/css" href="node_modules/bootstrap/dist/css/bootstrap.css">
    <link rel="stylesheet" type="text/css" href="css/main.css">
  </head>
  <body>
    <section id="react"></section>
    <script src="bundle.js"></script>
  </body>
</html>

 

注意,這裏面引用的bundle.js文件很是重要,他是咱們打包後的入口文件,不引入它程序是跑不起來的。web

app.js文件是程序的入口文件,咱們在這裏處理簡單的相似路由的邏輯:npm

import React from 'react';
import Router from 'react-router';
import { DefaultRoute, Link, Route, RouteHandler } from 'react-router';
import HelloHandler from './hello.js';
let App = React.createClass({
  render() {
    return (
      <div className="nav">
        <Link to="app" className="homelink">Home  </Link>
        <Link to="hello" className="hellolink">  Say Hello</Link>
        {/* this is the importTant part */}
        <RouteHandler/>
      </div>
    );
  }
});
let routes = (
  <Route name="app" path="/" handler={App}>
    <Route name="hello" path="/hello" handler={HelloHandler}/>
  </Route>
);
Router.run(routes, function (Handler) {
  React.render(<Handler />, document.body);
});

 

相信你已經看到了ES6的身影,沒錯,在這裏,咱們寫ES6的代碼,只要新建js文件,咱們就在裏面寫ES6的代碼。

咱們在入口文件上放上了一個鏈接,分離咱們最熟悉的helloworld代碼。也是爲了方便之後咱們寫其餘的例子能夠有單獨的文件,易於管理和查看,就像下面看到的項目目錄同樣,一個js文件就是一個小例子的代碼。

hello.js:

import React from 'react';
let Hello = React.createClass({
    render() {
        return(<div>Hello World!</div>);
  }
});
export default Hello;

1.4 執行:

1 npm install

再加上一些必要的文件入口,咱們的項目如今看起來應該是這樣的:

從個人github上面fork下來的目錄應該是這樣的:

裏面包含了一些我已經寫好的小例子。固然,咱們按照上面的目錄來建立就沒錯啦。

1.5 程序跑起來,執行:

1 npm start

而後訪問[http://localhost:8080/webpack-dev-server/]咱們就能夠看到項目跑起來了。

 

2、理解React

隨着Facebook開源了React Native for Android,React的前景彷佛更加光明。它從最先的UI框架慢慢演變成了一套web應用的解決方案,而且它衍生出來的React Native更是承載着宏偉的目標:learn once, write anywhere。這對前端來講彷佛是種不可抗拒的吸引力。 

React有三個關鍵詞:

- Just the ui
- virtual dom
- data flow

要理解React,我從它的這三個關鍵詞入手。

2.1 Just the ui

React 負責UI層面的展示,儘管不少人用React做[MVC]架構中的View層,但這並非React的本意。

通常的狀況下,咱們在開發過程當中,一般會使用模板或者直接使用HTML來構建UI,而HTML是靜態的,使用模板在大多數狀況下是能夠知足需求的,可是在複雜的邏輯情境中就顯得有些吃力了,過多的if else或者邏輯控制在模板裏,都會讓代碼變得難以維護,固然這仍是說整個項目中使用統一的模板的狀況下。

React換了一種思路解決問題,它把UI拆分紅組件,而不是經過模板引擎和展現邏輯,使得它能夠易於拓展和維護。所以它引入了JSX這種語法規則,可讓咱們使用相似HTML的語法去寫js的函數調用。

2.2 virtual dom

瀏覽器渲染頁面的通常過程一般是這樣的:

1 加載html->生成DOM樹->解析css生成Render樹->生成頁面

 那麼React的virtual dom是怎麼作的呢?

1 生成virtual dom->diff->必要的DOM更新

在這裏面大部分的操做放在js中去完成,由於咱們都知道dom操做是很昂貴的。因此在通常的狀況下React的性能仍是很不錯的。

2.3 data flow

React中的數據流是沿着組件樹從上到下單向流動的。

這裏的data flow指的是一種應用架構的實現方式,好比說,數據存放在哪裏,在哪裏觸發事件,如何響應用戶操做。它不是React提供的什麼新功能,應該是React構建應用的實踐。咱們理解了以後的Flux或許就更加容易理解data flow這個概念了。

2.4 Flux overview

Flux是facebook配套React強推的一種應用架構思想。它利用數據的單向流動爲React的可複用的視圖組件提供了補充。

與React的數據流動方式相同,在Flux架構中,數據也是單向流動的:

簡單的說,全部的數據流動都會通過Dispatcher。Action能夠經過action creator產生並被提供給dispatcher,但多數狀況下action是經過用戶與views的交互產生。

在View層捕獲用戶的交互,產生一個Action,經過觸發註冊在Dispatcher上面的事件回調,使得相關的Store響應Action,而後會觸發到Store上面的onChange事件,進一步的更新View。

數據流動也始終是如上圖所示的單向流動的。

實踐了這個例子:[thinking in react]會對理解React的基本工做原理有很好地幫助。

 

3、Webpack入門

3.1 什麼是Webpack?

說Webpack是相似Grunt和Gulp同樣的打包工具並不合適,說Webpack是相似Browserify的模塊管理工具也還有點相似。然而Webpack作的事情遠不止這些。

Webpack出自facebook的Instagram團隊,在網上找到了比較好的對它主要特性的概括,以下:

1 同時支持CommonJS和AMD模塊(對於新項目,推薦直接使用CommonJS);
2 串聯式模塊加載器以及插件機制,讓其具備更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持;
3 能夠基於配置或者智能分析打包成多個文件,實現公共模塊或者按需加載;
4 支持對CSS,圖片等資源進行打包,從而無需藉助Grunt或Gulp;
5 開發時在內存中完成打包,性能更快,徹底能夠支持開發過程的實時打包需求;
6 對sourcemap有很好的支持,易於調試。

Webpack將項目中的一切資源都看作是模塊,模塊之間能夠互相依賴,Webpack對他們作統一的管理,打包和發佈,用於咱們的工做流中。

3.2 webpack.config.js文件

在前面咱們跑起來了的例子中,咱們能夠看到webpack.config.js文件,全部跟webpack有關的工做,都在這個文件中進行。

它看起來,目前是這樣的:

var webpack = require('webpack');
module.exports = {
    entry: [
      'webpack/hot/only-dev-server',
      "./js/app.js"
    ],
    output: {
        path: './build',
        filename: "bundle.js"
    },
    module: {
        loaders: [
            { test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
            { test: /\.css$/, loader: "style!css" },
            {test: /\.less/,loader: 'style-loader!css-loader!less-loader'}
        ]
    },
    resolve:{
        extensions:['','.js','.json']
    },
    plugins: [
             new webpack.NoErrorsPlugin()
    ]
};

它一般放在根目錄下,他本身也是一個標準的Commonjs模塊,咱們可能已經看到了require,module.exports這樣的標誌性關鍵詞。

它的主要的配置參數有:

- entry:

entry: [
      'webpack/hot/only-dev-server',
      "./js/app.js"
    ],

它定義了打包的入口文件,數組中的文件會按順序進行,而且它會自行解決依賴問題。

在這裏其實咱們還定義了Webpack開發服務器,webpack-dev-server,咱們能夠在package.json文件中看到:

"scripts": {
    "start": "webpack-dev-server --hot --progress --colors",
    "build": "webpack --progress --colors"
  },

這也是咱們npm start啓動了服務器以後訪問http://localhost:8080/webpack-dev-server/能夠訪問到頁面的緣由。

- output:

output: {
        path: './build',
        filename: "bundle.js"
    },

它定義了輸出文件的的位置,包括路徑,文件名,還可能有運行時的訪問路徑(publicPath)參數。

- module:

webpack將全部的資源都看作是模塊,而模塊就須要加載器:

module: {
        loaders: [
            { test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
            { test: /\.css$/, loader: "style!css" },
            {test: /\.less/,loader: 'style-loader!css-loader!less-loader'}
        ]
    },

對於不一樣的文件,咱們能夠自行配置使用不一樣的加載器。也能夠自行實現合心意的加載器。

在這裏咱們配置了babel-loader,可讓咱們在js文件中爲所欲爲的開始寫ES6規範的代碼。

Webpack的加載器之間能夠進行串聯,一個加載器的輸出能夠成爲另外一個加載器的輸入。好比LESS文件先經過less-load處理成css,而後再經過css-loader加載成css模塊,最後由style-loader加載器對其作最後的處理,從而運行時能夠經過style標籤將其應用到最終的瀏覽器環境。

- resolve:

 resolve:{
       extensions:['','.js','.json']
   },

Webpack 是使用相似 Browserify 的方式在本地按目錄對依賴進行查找。

resolve屬性中的extensions數組中用於配置程序能夠自行補全哪些後綴。好比說咱們要require一個common.js文件,添加了這個配置咱們只要寫:require('common');就能夠了。

- plugin:

plugins: [
    new webpack.NoErrorsPlugin()
  ]

咱們能夠在plugin參數中配置咱們須要用到的各類各樣的插件。好比咱們想將多個文件分開打包,可能會用到:

 {
   entry: { a: "./a", b: "./b" },
   output: { filename: "[name].js" },
   plugins: [ new webpack.CommonsChunkPlugin("init.js") ]
 }

 

 

4、如今開始探索&&擴展閱讀

面向將來的ES6,模塊化的支持彷佛已成定局。咱們經過從webpack中的配置便可立刻開始編寫ES6的代碼。

經過打造這樣的工做環境,咱們能夠同時使用多種面向將來的新技術開始新的探索。

如今就開始探索吧!不要等到將來到來,卻發現本身還沒作好準備。

 

擴展閱讀:

[基於webpack的前端工程化探索]

[webpack入門]

[webpack-howto]

[webpack home]

相關文章
相關標籤/搜索