Webpack配置

Webpack是目前基於React和Redux開發的應用的主要打包工具。我想使用Angular 2或其餘框架開發的應用也有不少在使用Webpack。css

當我第一次看到Webpack的配置文件時,它看起來很是的陌生,我很是的疑惑。通過一段時間的嘗試以後我認爲這是由於Webpack只是使用了比較特別的語法和引入了新的原理,所以會讓使用者感到疑惑。這些也是致使Webpack不被人熟悉的緣由。html

由於剛開始使用Webpack很讓人疑惑,我以爲有必要寫幾篇介紹Webpack的功能和特性的文章以幫助初學者快速理解。此文是最開始的一篇。node

Webpack的核心原理react

Webpack的兩個最核心的原理分別是:webpack

  1. 一切皆模塊 正如js文件能夠是一個「模塊(module)」同樣,其餘的(如css、image或html)文件也可視做模 塊。所以,你能夠require('myJSfile.js')亦能夠require('myCSSfile.css')。這意味着咱們能夠將事物(業務)分割成更小的易於管理的片斷,從而達到重複利用等的目的。web

  2. 按需加載 傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。npm

好了,下面來看看那些使人困惑的部分吧。json

  1. 開發模式和生產模式數組

    首先要知道的是Webpack有許許多多的特性,一些是」開發模式「下才有的,一些是」生產模式「下才有的,還有一些是兩種模式下都有的。瀏覽器

    輸入圖片說明

一般使用到Webpack如此多特性的項目都會有兩個比較大的Webpack配置文件 爲了生成bundles文件你可能在package.json文件加入以下的scripts項:

"scripts": {
// 運行npm run build 來編譯生成生產模式下的bundles
"build": "webpack --config webpack.config.prod.js",
// 運行npm run dev來生成開發模式下的bundles以及啓動本地server
"dev": "webpack-dev-server"
}
  1. webpack CLI 和webpack-dev-server

    值得注意的是,Webpack做爲模塊打包工具,提供兩種用戶交互接口:

    a.Webpack CLI tool:默認的交互方式(已隨Webpack自己安裝到本地)

    b.webpack-dev-server:一個Node.js服務器(須要開發者從npm自行安裝)

    Webpack CLI(有利於生產模式下打包) 這種方式能夠從命令行獲取參數也能夠從配置文件(默認叫webpack.config.js)獲取,將獲取到的參數傳入 Webpack來打包。

    固然你也能夠從命令行(CLI)開始學習Webpack,之後你可能主要在生產模式下使用到它。

    用法:

    方式1:

     

// 全局模式安裝webpack npm install webpack --g // 在終端輸入 $ webpack // <--使用webpack.config.js生成bundle ```

方式 2 :

```
// 非全局模式安裝webpack而後添加到package.json依賴裏邊
npm install webpack --save
// 添加build命令到package.json的scripts配置項
"scripts": {
 "build": "webpack --config webpack.config.prod.js -p",

 }
// 用法:
"npm run build"
webpack-dev-server(有利於在開發模式下編譯):    這是一個基於Express.js框架開發的web server,默認監聽8080端口。server內部調用Webpack,這樣作的好處是提供了額外的功能如熱更新「Live Reload」以及熱替換「Hot Module Replacement」(即HMR)。

 用法:

   方式 1:

 ```
// 全局安裝
npm install webpack-dev-server --save
// 終端輸入
$ webpack-dev-server --inline --hot
用法 2:

```

// 添加到package.json scripts "scripts": { "start": "webpack-dev-server --inline --hot", } // 運行: $ npm start // 瀏覽器預覽: http://localhost:8080

Webpack VS Webpack-dev-server選項

   注意像inline和hot這些選項是Webpack-dev-server特有的,而另外的如hide-modules則是CLI模式特有的選項。

    webpack-dev-server CLI選項和配置項 : 另外值得注意的是你能夠經過如下兩種方式向webpack-dev-server傳入參數:

    1.經過webpack.config.js文件的"devServer"對象
    ```
// 經過webpack.config.js傳參
devServer: {
  inline: true,
  hot:true
}
2.經過CLI選項

// 經過CLI傳參

webpack-dev-server --hot --inline

我發現有時devServer配置項(hot: true 和inline: true)不生效,我更偏向使用以下的方式向CLI傳遞參數:

```

// package.json { "scripts": "webpack-dev-server --hot --inline" } //注意:肯定你沒有同時傳入hot:true和-hot

webpack-dev-server的「hot」 和 「inline」選項 : 「inline」選項會爲入口頁面添加「熱加載」功能,「hot」選項則開啓「熱替換(Hot Module Reloading)」,即嘗試從新加載組件改變的部分(而不是從新加載整個頁面)。若是兩個參數都傳入,當資源改變時,webpack-dev-server將會先嚐試HRM(即熱替換),若是失敗則從新加載整個入口頁面。

    // 當資源發生改變,如下三種方式都會生成新的bundle,可是又有區別:

    ```
// 1. 不會刷新瀏覽器
$ webpack-dev-server
//2. 刷新瀏覽器
$ webpack-dev-server --inline
//3. 從新加載改變的部分,HRM失敗則刷新頁面
$ webpack-dev-server  --inline --hot
  1. 「entry」:值分別是字符串、數組和對象的狀況

    Enter配置項告訴Webpack應用的根模塊或起始點在哪裏,它的值能夠是字符串、數組或對象。這看起來可能使人困惑,由於不一樣類型的值有着不一樣的目的。 像絕大多數app同樣,假若你的應用只有一個單一的入口,enter項的值你可使用任意類型,最終輸出的結果都是同樣的。 圖片描述

    enter:數組類型

    可是,若是你想添加多個彼此不互相依賴的文件,你可使用數組格式的值。 例如,你可能在html文件裏引用了「googleAnalytics.js」文件,能夠告訴Webpack將其加到bundle.js的最後。 圖片描述

    enter:對象

    如今,假設你的應用是多頁面的(multi-page application)而不是SPA,有多個html文件(index.html和profile.html)。而後你經過一個對象告訴Webpack爲每個html生成一個bundle文件。 如下的配置將會生成兩個js文件:indexEntry.js和profileEntry.js分別會在index.html和profile.html中被引用。

    圖片描述

    用法:

//profile.html
<script src=」dist/profileEntry.js」></script>
//index.html
<script src=」dist/indexEntry.js」></script>

注意:文件名取自「entry」對象的鍵名。

enter:混合類型

你也能夠在enter對象裏使用數組類型,例以下面的配置將會生成3個文件:vender.js(包含三個文件),index.js和profile.js文件。

  ![圖片描述](https://static.oschina.net/uploads/img/201705/03123917_AjGS.png "在這裏輸入圖片標題")
  1. output:「path」項和「publicPath」項

    output項告訴webpack怎樣存儲輸出結果以及存儲到哪裏。output的兩個配置項「path」和「publicPath」可能會形成困惑。

    「path」僅僅告訴Webpack結果存儲在哪裏,然而「publicPath」項則被許多Webpack的插件用於在生產模式下更新內嵌到css、html文件裏的url值。

    圖片描述

    例如,在localhost(譯者注:即本地開發模式)裏的css文件中邊你可能用「./test.png」這樣的url來加載圖片,可是在生產模式下「test.png」文件可能會定位到CDN上而且你的Node.js服務器多是運行在HeroKu上邊的。這就意味着在生產環境你必須手動更新全部文件裏的url爲CDN的路徑。

    然而你也可使用Webpack的「publicPath」選項和一些插件來在生產模式下編譯輸出文件時自動更新這些url。

    圖片描述

     

// 開發環境:Server和圖片都是在localhost(域名)下 .image { background-image: url('./test.png'); } // 生產環境:Server部署下HeroKu可是圖片在CDN上 .image { background-image: url('https://someCDN/test.png'); }

5. 模塊加載和鏈式模塊加載

    模塊加載器是可自由添加的Node模塊,用於將不一樣類型的文件「load」或「import」並轉換成瀏覽器能夠識別的類型,如js、Stylesheet等。更高級的模塊加載器甚至能夠支持使用ES6裏邊的「require」或「import」引入模塊。

    例如,你可使用babel-loader來將使用ES6語法寫成的文件轉換成ES5:

    ```
module: {
 loaders: [{
  test: /\.js$/, // 匹配.js文件,若是經過則使用下面的loader
  exclude: /node_modules/, // 排除node_modules文件夾
  loader: 'babel' // 使用babel(babel-loader的簡寫)做爲loader
 }]
鏈式(管道式)的加載器(從右往左執行)多個loader能夠用在同一個文件上而且被鏈式調用。鏈式調用時從右到左執行且loader之間用「!」來分割。

例如,假設咱們有一個名爲「myCssFile.css」的css文件,而後咱們想將它的內容使用style標籤內聯到最終輸出的html裏邊。咱們可使用css-loader和style-loader兩個loader來達到目的。

```

module: { loaders: [{ test: /.css$/, loader: 'style!css' //(short for style-loader!css-loader) }]

這裏展現它是如何工做的:
   ![輸入圖片說明](https://static.oschina.net/uploads/img/201705/03135006_8uHF.png "在這裏輸入圖片標題")

    Webpack在模塊顳部搜索在css的依賴項,即Webpack檢查js文件是否有「require('myCssFile.css')」的引用,若是它發現有css的依賴,Webpack將css文件交給「css-loader」去處理css-loader加載全部的css文件以及css自身的依賴(如,[@import](https://my.oschina.net/u/3201731) 其餘css)到JSON對象裏,Webpack而後將處理結果傳給「style-loader」

    style-loader接受JSON值而後添加一個style標籤並將其內嵌到html文件裏

6. loader自身能夠配置
模塊加載器(loader)自身能夠根據傳入不一樣的參數進行配置。
在下面的例子中,咱們能夠配置url-loader來將小於1024字節的圖片使用DataUrl替換而大於1024字節的圖片使用url,咱們能夠用以下兩種方式經過傳入「limit「參數來實現這一目的:
![圖片描述](https://static.oschina.net/uploads/img/201705/03124443_CHYU.png "在這裏輸入圖片標題")

7. .babelrc 文件

    babal-loader使用」presets「配置項來標識如何將ES6語法轉成ES5以及如何轉換React的JSX成js文件。咱們能夠用以下的方式使用」query「參數傳入配置:

    ```
module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /(node_modulesbower_components)/,
      loader: 'babel',
      query: {
        presets: ['react', 'es2015']
      }
    }
  ]
}
然而在不少項目裏babal的配置可能比較大,所以你能夠把babal-loader的配置項單獨保存在一個名爲」.babelrc「的文件中,在執行時babal-loader將會自動加載.babelrc文件。

因此在不少例子裏,你可能會看到:

```

//webpack.config.js module: { loaders: [ { test: /.jsx?$/, exclude: /(node_modulesbower_components)/, loader: 'babel' } ] } //.bablerc { presets: ['react', 'es2015'] } ```

  1. 插件

    插件通常都是用於輸出bundle的node模塊。

    例如,uglifyJSPlugin獲取bundle.js而後壓縮和混淆內容以減少文件體積。

    相似的extract-text-webpack-plugin內部使用css-loader和style-loader來收集全部的css到一個地方最終將結果提取結果到一個獨立的」styles.css「文件,而且在html裏邊引用style.css文件。

     

//webpack.config.js // 獲取全部的.css文件,合併它們的內容而後提取css內容到一個獨立的」styles.css「裏 var ETP = require("extract-text-webpack-plugin");

module: { loaders: [ {test: /.css$/, loader:ETP.extract("style-loader","css-loader") } ] }, plugins: [ new ExtractTextPlugin("styles.css") //Extract to styles.css file ] }

注意:若是你只是想把css使用style標籤內聯到html裏,你沒必要使用extract-text-webpack-plugin,僅僅使用css loader和style loader便可:

    ```
module: {
 loaders: [{
  test: /\.css$/,
  loader: 'style!css' // (short for style-loader!css-loader)
 }]
  1. 加載器(loader)和插件

    你可能已經意識到了,Loader處理單獨的文件級別而且一般做用於包生成以前或生成的過程當中。

    而插件則是處理包(bundle)或者chunk級別,且一般是bundle生成的最後階段。一些插件如commonschunkplugin甚至更直接修改bundle的生成方式。

    1. 處理文件的擴展名

    不少Webpack的配置文件都有一個resolve屬性,而後就像下面代碼所示有一個空字符串的值。空字符串在此是爲了resolve一些在import文件時不帶文件擴展名的表達式,如require('./myJSFile')或者import myJSFile from './myJSFile'(譯者注:實際就是自動添加後綴,默認是當成js文件來查找路徑)

     

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

就這麼多。

做者: 極客教程 
連接:http://www.imooc.com/article/13357
來源:慕課網
相關文章
相關標籤/搜索