React自發布以來吸引了愈來愈多的開發者,React開發和模塊管理的主流工具webpack也被你們所熟知。那麼webpack有哪些優點,能夠成爲最主流的React開發工具呢?css
CommonJS和AMD是用於JavaScript模塊管理的兩大規範,前者定義的是模塊的同步加載,主要用於NodeJS;然後者則是異步加載,經過requirejs等工具適用於前端。隨着npm成爲主流的JavaScript組件發佈平臺,愈來愈多的前端項目也依賴於npm上的項目,或者自身就會發布到npm平臺。所以,讓前端項目更方便的使用npm上的資源成爲一大需求。html
web開發中經常使用到的靜態資源主要有JavaScript、CSS、圖片、Jade等文件,webpack中將靜態資源文件稱之爲模塊。webpack是一個module bundler(模塊打包工具),其能夠兼容多種js書寫規範,且能夠處理模塊間的依賴關係,具備更強大的js模塊化的功能。Webpack對它們進行統一的管理以及打包發佈,其官方主頁用下面這張圖來講明Webpack的做用:前端
Webpack具備requireJs和browserify的功能,但仍有不少本身的新特性:node
1. 對 CommonJS 、 AMD 、ES6的語法作了兼容 2. 對js、css、圖片等資源文件都支持打包 3. 串聯式模塊加載器以及插件機制,讓其具備更好的靈活性和擴展性,例如提供對CoffeeScript、ES6的支持 4. 有獨立的配置文件webpack.config.js 5. 能夠將代碼切割成不一樣的chunk,實現按需加載,下降了初始化時間 6. 支持 SourceUrls 和 SourceMaps,易於調試 7. 具備強大的Plugin接口,大可能是內部插件,使用起來比較靈活 8.webpack 使用異步 IO 並具備多級緩存。這使得 webpack 很快且在增量編譯上更加快
以 react-sample 爲例,簡單說明 Webpack 如何打包一個 React 組件,其目錄結構以下:react
其中Hello.js定義了一個簡單的React組件,使用ES6語法:jquery
/** * Created by pomy on 15/11/4. */ import React, {Component} from 'react'; class Hello extends Component { render(){ return ( <div>Hello, {this.props.name}!</div> ); } }
entry.js是入口文件,將一個Hello組件輸出到界面:webpack
/** * Created by pomy on 15/11/4. */ import React from 'react'; import Hello from './hello'; React.render(<Hello name="Nate" />, document.body);
index.html的內容以下:git
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>React Sample</title> </head> <body> <script src="./assets/bundle.js"></script> </body> </html>
webpack.config.js文件一般放在項目的根目錄中,它自己也是一個標準的Commonjs規範的模塊:github
var path = require('path'); module.exports = { entry: path.resolve(__dirname, './src/entry.js'), output: { path: path.resolve(__dirname, './assets'), filename: 'bundle.js' }, module: { loaders: [ { test: /\.js?$/, loaders: ['babel'], exclude: /node_modules/ }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/} ] }, resolve:{ extensions:['','.js','.json'] }, };
整個代碼在 這裏,clone以後,切換到react-sample目錄下,在終端運行 npm i && npm run build
進行打包,打包後的文件名是 bundle.js, 所在相對目錄是 /assets。至此,webpack打包過程就ok了。web
webpack 能夠做爲全局的npm模塊安裝,也能夠在當前項目中安裝。
npm install -g webpack npm install --save-dev webpack
對於全局安裝的webpack,直接執行此命令會默認使用當前目錄的webpack.config.js做爲配置文件。若是要指定另外的配置文件,能夠執行:
webpack —config webpack.custom.config.js
每一個項目下都必須配置有一個 webpack.config.js ,它的做用如同常規的 gulpfile.js/Gruntfile.js ,就是一個配置項,告訴 webpack 它須要作什麼。
前文說了,webpack.config.js文件一般放在項目的根目錄中,它自己也是一個標準的Commonjs規範的模塊。在導出的配置對象中有幾個關鍵的參數:
entry
entry 參數定義了打包後的入口文件,能夠是個字符串或數組或者是對象;若是是數組,數組中的全部文件會打包生成一個filename文件;若是是對象,能夠將不一樣的文件構建成不一樣的文件:
{ entry: { page1: "./page1", //支持數組形式,將加載數組中的全部模塊,但以最後一個模塊做爲輸出 page2: ["./entry1", "./entry2"] }, output: { path: "dist/js/page", publicPath: "/output/", filename: "[name].bundle.js" } }
該段代碼最終會生成一個 page1.bundle.js 和 page2.bundle.js,並存放到 ./dist/js/page 文件夾下
output
output參數是個對象,定義了輸出文件的位置及名字:
output: { path: "dist/js/page", publicPath: "/output/", filename: "[name].bundle.js" } path: 打包文件存放的絕對路徑 publicPath: 網站運行時的訪問路徑 filename:打包後的文件名
當咱們在entry中定義構建多個文件時,filename能夠對應的更改成[name].js用於定義不一樣文件構建後的名字。
module
在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等靜態文件都是模塊,不一樣模塊的加載是經過模塊加載器(webpack-loader)來統一管理的。loaders之間是能夠串聯的,一個加載器的輸出能夠做爲下一個加載器的輸入,最終返回到JavaScript上:
module: { //加載器配置 loaders: [ //.css 文件使用 style-loader 和 css-loader 來處理 { test: /\.css$/, loader: 'style-loader!css-loader' }, //.js 文件使用 jsx-loader 來編譯處理 { test: /\.js$/, loader: 'jsx-loader?harmony' }, //.scss 文件使用 style-loader、css-loader 和 sass-loader 來編譯處理 { test: /\.scss$/, loader: 'style!css!sass?sourceMap'}, //圖片文件使用 url-loader 來處理,小於8kb的直接轉爲base64 { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} ] }
test 項表示匹配的資源類型,loader或loaders 項表示用來加載這種類型的資源的loader,loader的使用能夠參考 using loaders,更多的loader能夠參考 list of loaders。
!
用來定義loader的串聯關係,」-loader」是能夠省略不寫的,多個loader之間用「!」鏈接起來,但全部的加載器都須要經過npm來加載。
此外,還能夠添加用來定義png、jpg這樣的圖片資源在小於10k時自動處理爲base64圖片的加載器:
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=10000' }
給css和less還有圖片添加了loader以後,咱們不只能夠像在node中那樣require js文件了,咱們還能夠require css、less甚至圖片文件:
require('./bootstrap.css'); require('./myapp.less'); var img = document.createElement('img'); img.src = require('./glyph.png');
注意,require()還支持在資源path前面指定loader,即require(![loaders list]![source path])形式:
require("!style!css!less!bootstrap/less/bootstrap.less"); // 「bootstrap.less」這個資源會先被"less-loader"處理, // 其結果又會被"css-loader"處理,接着是"style-loader" // 可類比pipe操做
require() 時指定的loader會覆蓋配置文件裏對應的loader配置項。
resolve
webpack在構建包的時候會按目錄的進行文件的查找,resolve屬性中的extensions數組中用於配置程序能夠自行補全哪些文件後綴:
resolve: { //查找module的話從這裏開始查找 root: '/pomy/github/flux-example/src', //絕對路徑 //自動擴展文件後綴名,意味着咱們require模塊能夠省略不寫後綴名 extensions: ['', '.js', '.json', '.scss'], //模塊別名定義,方便後續直接引用別名,無須多寫長長的地址 alias: { AppStore : 'js/stores/AppStores.js',//後續直接 require('AppStore') 便可 ActionType : 'js/actions/ActionType.js', AppAction : 'js/actions/AppAction.js' } }
而後咱們想要加載一個js文件時,只要 require(‘common’)就能夠加載common.js文件了。
注意一下, extensions 第一個是空字符串 !
對應不須要後綴的狀況.
plugin
webpack提供了[豐富的組件]用來知足不一樣的需求,固然咱們也能夠自行實現一個組件來知足本身的需求:
plugins: [ //your plugins list ]
在webpack中編寫js文件時,能夠經過require的方式引入其餘的靜態資源,可經過loader對文件自動解析並打包文件。一般會將js文件打包合併,css文件會在頁面的header中嵌入style的方式載入頁面。但開發過程當中咱們並不想將樣式打在腳本中,最好能夠獨立生成css文件,之外鏈的形式加載。這時extract-text-webpack-plugin插件能夠幫咱們達到想要的效果。須要使用npm的方式加載插件,而後參見下面的配置,就能夠將js中的css文件提取,並以指定的文件名來進行加載。
npm install extract-text-webpack-plugin –save-dev
plugins: [ new ExtractTextPlugin('styles.css') ]
externals
當咱們想在項目中require一些其餘的類庫或者API,而又不想讓這些類庫的源碼被構建到運行時文件中,這在實際開發中頗有必要。此時咱們就能夠經過配置externals參數來解決這個問題:
externals: { "jquery": "jQuery" }
這樣咱們就能夠放心的在項目中使用這些API了:var jQuery = require(「jquery」);
context
當咱們在require一個模塊的時候,若是在require中包含變量,像這樣:
require("./mods/" + name + ".js");
那麼在編譯的時候咱們是不能知道具體的模塊的。但這個時候,webpack也會爲咱們作些分析工做:
因而這個時候爲了更好地配合wenpack進行編譯,咱們能夠給它指明路徑,像在cake-webpack-config中所作的那樣(咱們在這裏先忽略abcoption的做用):
var currentBase = process.cwd(); var context = abcOptions.options.context ? abcOptions.options.context : path.isAbsolute(entryDir) ? entryDir : path.join(currentBase, entryDir);
關於 webpack.config.js 更詳盡的配置能夠參考 這裏
webpack的使用一般有三種方式:
一、命令行使用:webpack 其中entry.js是入口文件,result.js是打包後的輸出文件
二、node.js API使用:
var webpack = require('webpack'); webpack({ //configuration }, function(err, stats){});
三、默認使用當前目錄的 webpack.config.js 做爲配置文件。若是要指定另外的配置文件,能夠執行:webpack –config webpack.custom.config.js
webpack 的執行也很簡單,直接執行
webpack --display-error-details
webpack的使用和browserify有些相似,下面列舉幾個經常使用命令:
webpack 最基本的啓動webpack命令 webpack -w 提供watch方法,實時進行打包更新 webpack -p 對打包後的文件進行壓縮 webpack -d 提供SourceMaps,方便調試 webpack --colors 輸出結果帶彩色,好比:會用紅色顯示耗時較長的步驟 webpack --profile 輸出性能數據,能夠看到每一步的耗時 webpack --display-modules 默認狀況下 node_modules 下的模塊會被隱藏,加上這個參數能夠顯示這些被隱藏的模塊