你一定喜歡看的 Webpack 2.× 入門實戰(zhàn)

SpringBride

最近在學(xué)習(xí) Webpack,網(wǎng)上大多數(shù)入門教程都是基于 Webpack 1.x 版本的,我學(xué)習(xí) Webpack 的時候是看了 zhangwang<<入門 Webpack往湿,看這篇就夠了>> 寫的非常好,不過是基于 Webpack 1.x 版本的,語法上和 Webpack 2.x 有一點不同.我學(xué)習(xí)時是使用 Webpack 2.6.1 版本,所以我就尋思著基于 zhangwang<<入門 Webpack,看這篇就夠了>> 寫下這篇 Webpack 2.x 的入門實戰(zhàn),是我學(xué)習(xí) Webpack 的記錄.聽說 Webpack 3.x 版本快要出了,不得不感嘆前端領(lǐng)域發(fā)展的真是太快了!

Webpack 是什么?

Webpack 是前端資源模塊化管理和打包工具惋戏。

Webpack 可以將許多松散的模塊按照依賴和規(guī)則打包成符合生產(chǎn)環(huán)境部署的前端資源领追。

Webpack 可以將按需加載的模塊進行代碼分隔,等到實際需要的時候再異步加載响逢。

Webpack 通過 loader 的轉(zhuǎn)換绒窑,任何形式的資源都可以視作模塊,比如 CommonJs 模塊舔亭、 AMD 模塊些膨、 ES6 模塊、CSS钦铺、圖片订雾、 JSON、Coffeescript矛洞、 LESS洼哎、 SASS 等。

一圖勝千言,下圖足夠說明上面巴巴拉拉一大堆是啥了!

bundle your assets

對于模塊的組織,通常有如下幾種方法:

  • 分開寫幾個 js 文件,使用 script 標簽加載.
  • CommonJS 進行同步加載, Node.js 就使用這種方式.
  • AMD進行異步加載, require.js 使用這種方式.
  • 新的 ES6 模塊.

Webpack 的特點

  • 豐富的插件噩峦,流行的插件都有,方便進行開發(fā)工作.
  • 大量的加載器锭沟,便于處理和加載各種靜態(tài)資源.
  • 將按需加載的模塊進行代碼分隔,等到實際需要的時候再異步加載.

Webpack 的優(yōu)勢

  • Webpack 以 commonJS 的形式來書寫腳本识补,但對 AMD / CMD / ES6 模塊 的支持也很全面族淮,方便舊項目進行代碼遷移。
  • 所有資源都能模塊化凭涂。
  • 開發(fā)便捷祝辣,能替代部分 Grunt / Gulp 的工作,比如打包切油、壓縮混淆较幌、圖片轉(zhuǎn) base64、SASS 解析成 CSS 等白翻。
  • 擴展性強,插件機制完善绢片,特別是支持模塊熱替換(見 模塊熱替換 )的功能讓人眼前一亮。

Webpack 與 Grunt / Gulp

在沒有學(xué)習(xí) Webpack 之前我對 Webpack、Grunt雏逾、Gulp 的認識很模糊,只知道好像這三個東西都是前端自動化工具,都是用來使前端自動化惠毁、模塊化、工程化的,這三者是可以替代彼此的前端工具.

其實 Webpack 和 Gulp / Grunt 并沒有太多的可比性熙涤,Gulp / Grunt 是一種能夠優(yōu)化前端開發(fā)流程的自動化工具阁苞,而 Webpack 是一種模塊化的解決方案,不過 Webpack 的優(yōu)點使得 Webpack 可以替代 Gulp / Grunt 一部分工作祠挫。

Grunt / Gulp 的工作方式是:在一個配置文件中那槽,指明對某些文件需要進行哪些處理,例如:編譯、組合等舔、壓縮等任務(wù)的具體步驟骚灸,Grunt / Gulp 之后可以自動替你完成這些任務(wù)。Grunt / Gulp的工作流程如下圖:

Gulp / Grunt

Webpack 的工作方式是:把你的項目當做一個整體慌植,通過一個給定的主文件( 如:index.js )甚牲,Webpack 將從這個文件開始找到你的項目的所有依賴文件,使用 loaders 處理它們蝶柿,最后打包為一個瀏覽器可識別的 JavaScript 文件丈钙。Webpack工作方式如下圖:

Webpack

如果實在要進行比較,Webpack 的處理速度更快更直接,因為 Webpack 的歷史包袱小.Webpack 還能打包更多不同類型的文件。

開始使用 Webpack

初步了解 Webpack 后交汤,就可以開始學(xué)習(xí)使用 Webpack雏赦。這里會以一個小的 Demo 為例子來一步一步進行動手學(xué)習(xí)!

新建 Webpack 項目

1. 新建一個文件夾,命名為 webpack-demo,webpack-demo 就是你的項目名,項目名建議使用小寫字母,并且不帶空格,不能含有大寫字母.

2. 安裝 Webpack,Webpack 可以使用 npm 安裝,如果你還不知道 npm 為何物,請 Google,也可以參考 Node.js 安裝配置NPM 使用介紹快速了解喉誊、安裝 npm.

使用終端在該文件夾中執(zhí)行下述指令就可以完成安裝,由于網(wǎng)絡(luò)原因安裝過程可能需要一些時間邀摆。

//全局安裝
npm install -g webpack
//安裝到你的項目目錄
npm install --save-dev webpack

Webpack 可以全局安裝,也可以安裝到你的項目目錄.剛開始學(xué)習(xí) Webpack 為了方便,建議同時全局安裝和安裝到你的項目目錄.

3. 在 webpack-demo 文件夾中創(chuàng)建一個 package.json 文件,這是一個標準的 npm 說明文件伍茄,里面蘊含了豐富的信息栋盹,包括當前項目的依賴模塊,自定義的腳本任務(wù)等等敷矫。在終端中使用 npm init 命令可以自動創(chuàng)建這個 package.json 文件.

npm init

輸入這個命令后例获,終端會問你一系列諸如項目名稱,項目版本,項目描述,入口文件,作者等信息,不過不用擔(dān)心曹仗,如果你不準備在 npm 中發(fā)布你的模塊榨汤,這些問題的答案都不重要,回車默認即可.這些信息今后都可以更改 package.json 來修改,所以不用擔(dān)心.

4. 在 webpack-demo 文件夾中創(chuàng)建兩個文件夾 app 文件夾和 public 文件夾, app 文件夾用來存放原始數(shù)據(jù),例如: SASS 文件怎茫、LESS 文件收壕、JavaScript 模塊等,public 文件夾用來存放經(jīng)過 Webpack 處理過的 app 文件夾數(shù)據(jù),這也是準備給瀏覽器讀取的數(shù)據(jù),其中包括使用 Webpack 打包后的 js 文件等轨蛤。在這里還需要在 public 文件夾中創(chuàng)建 index.html 文件.在 app 文件夾中創(chuàng)建 Greeter.js 和 main.js 文件蜜宪,此時項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

5. 在 public 文件夾中的 index.html 文件只有最基礎(chǔ)的 html 代碼,它唯一的目的就是加載打包后的 js 文件 bundle.js.

// index.html

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <title>webpack-demo</title>
</head>

<body>
    <div id='root'>
    </div>
    <script type="text/javascript" src="bundle.js"></script>
</body>

</html>

6. 在 app 文件夾中的 Greeter.js 只包括一個用來返回問候信息的 html 元素的函數(shù)祥山。

// Greeter.js

module.exports = function() {
    var greet = document.createElement('div');
    greet.textContent = "Hi there and greetings!";
    return greet;
}

7. 在 app 文件夾中的 main.js 用來把 Greeter 模塊(其實可以簡單的把它看作 Greeter.js)返回的節(jié)點插入頁面圃验。

// main.js

var greeting = require('./Greeter.js');
document.getElementById('root').appendChild(greeting());

Webpack 配置文件

Webpack 配置文件其實也是一個簡單的 JavaScript 模塊,可以把所有與項目構(gòu)建相關(guān)的信息放在里面缝呕。在 webpack-demo 文件夾根目錄下新建一個名為 webpack.config.js 的文件澳窑,并在其中進行最簡單的配置.如下所示,它包含入口文件路徑和存放打包后文件的地方路徑供常。

// webpack.config.js

module.exports = {
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    }
}

注:__dirname 是 node.js 中的一個全局變量摊聋,它指向當前 js 文件所在的目錄.

現(xiàn)在只需要在終端里運行 webpack 命令就可以了,這條命令會自動參考 webpack.config.js 文件中的配置選項打包你的項目话侧,輸出結(jié)果如下:

終端結(jié)果

此時項目的 public 文件夾下也會出現(xiàn)打包好的 bundle.js 文件.此時項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

可以看出 webpack 同時編譯了 main.js 和 Greeter.js,打開 public 目錄下的 index.html 文件,就可以看到最終效果,如下圖:

最終效果

利用 npm 更快捷的執(zhí)行打包任務(wù)

通過 Webpack 配置文件和執(zhí)行 webpack 命令其實是比較煩人且容易出錯的栗精,不過值得慶幸的是 npm 可以引導(dǎo)任務(wù)執(zhí)行,對其進行配置后可以使用簡單的 npm start 命令來代替這些繁瑣的命令瞻鹏。在 package.json 中對 npm 的腳本部分進行相關(guān)設(shè)置悲立,相當于把 npm 的 start 命令指向 webpack 命令,設(shè)置方法如下:

// package.json

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "webpack"
    },
    "author": "",
    "license": "ISC"
}

執(zhí)行 npm start 后命令行的輸出顯示:

npmStartTermialResult

現(xiàn)在只需要使用 npm start 就可以打包文件了.打開 public 目錄下的 index.html 文件,看到的最終效果是不是與之前的一樣.

利用 Webpack 生成 Source Maps

簡單說新博,Source Maps 就是一個信息文件薪夕,里面儲存著位置信息。也就是說赫悄,轉(zhuǎn)換后的代碼的每一個位置原献,所對應(yīng)的轉(zhuǎn)換前的位置.有了它馏慨,出錯的時候,除錯工具將直接顯示原始代碼姑隅,而不是轉(zhuǎn)換后的代碼写隶。這無疑給開發(fā)者帶來了很大方便.為了方便調(diào)試可以利用 Webpack 生成 Source Maps.

在 Webpack 的配置文件中配置 Source Maps,需要配置 devtool讲仰,它有以下四種不同的配置選項慕趴,各有優(yōu)缺點,描述如下:

  • source-map 在一個單獨的文件中產(chǎn)生一個完整且功能完全的文件鄙陡。這個文件具有最方便調(diào)試的 Source Maps冕房,但是這個文件會比較大,會減慢打包文件的構(gòu)建速度.
  • cheap-module-source-map 在一個單獨的文件中生成一個不帶列映射的 Source Maps,不帶列映射能夠提高項目構(gòu)建速度趁矾,但這也使得瀏覽器開發(fā)者工具只能對應(yīng)到具體的行耙册,不能對應(yīng)到具體的列,會對調(diào)試造成不便.
  • eval-source-map 在同一個文件中生成干凈的完整的 Source Maps毫捣。這個選項可以在不影響構(gòu)建速度的前提下生成完整的 Source Maps详拙,但是對打包后輸出的 js 文件的執(zhí)行具有性能和安全的隱患。不過在開發(fā)階段這是一個非常好的選項蔓同,但是在生產(chǎn)階段一定不要用這個選項.
  • cheap-module-eval-source-map 這是在打包文件時最快的生成 Source Maps 的方法溪厘,生成的Source Map 會和打包后的 js 文件同行顯示,沒有列映射牌柄,和 eval-source-map 選項具有相似的缺點,文件的執(zhí)行具有性能和安全的隱患.

上述選項由上到下打包速度越來越快,不過同時也具有越來越多的負面作用侧甫,較快的構(gòu)建速度的后果就是對打包的文件執(zhí)行有一定影響珊佣。在學(xué)習(xí)階段以及在小到中型的項目上,eval-source-map是一個很好的選項披粟,不過記得只在開發(fā)階段使用它.

編輯 webpack-demo 文件夾下的 webpack.config.js 文件配置 devtool 選項,生成 Source Maps 文件.配置 devtool 后的 webpack.config.js 文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    }
}

執(zhí)行 npm start 命令后就能生成對應(yīng)的 Source Maps,終端輸出信息如下圖:

終端輸出信息

此時項目中 public 文件夾下也生成了名為 bundle.js.map 的 Source Maps 文件.此時項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

使用 Webpack 構(gòu)建本地服務(wù)器

想不想讓你的瀏覽器監(jiān)測你修改的代碼咒锻,并自動刷新修改后的結(jié)果.其實 Webpack 提供一個可選的本地開發(fā)服務(wù)器,這個本地服務(wù)器基于 node.js 構(gòu)建守屉,可以實現(xiàn)你想要的這些功能惑艇,不過它是一個單獨的組件,在 Webpack 中進行配置之前需要單獨安裝它作為項目依賴.在終端中輸入下面的指令安裝對應(yīng)組件.建議同時全局安裝和安裝到你的項目目錄.

//全局安裝
npm install -g webpack-dev-server
//安裝到你的項目目錄
npm install --save-dev webpack-dev-server

devserver 作為 Webpack 配置選項中的一項拇泛,具有以下配置選項

  • contentBase 默認 webpack-dev-server 會為根文件夾提供本地服務(wù)器滨巴,如果想為另外一個目錄下的文件提供本地服務(wù)器,應(yīng)該在這里設(shè)置其所在目錄(本例設(shè)置到“public"文件夾下).
  • port 設(shè)置默認監(jiān)聽端口俺叭,如果省略恭取,默認為"8080".
  • inline 設(shè)置為 true,當源文件改變時會自動刷新頁面.
  • historyApiFallback 在開發(fā)單頁應(yīng)用時非常有用熄守,它依賴于 HTML5 history API蜈垮,如果設(shè)置為 true耗跛,所有的跳轉(zhuǎn)將指向 index.html.

編輯 webpack-demo 文件夾下的 webpack.config.js 文件配置以上選項.

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    }
}

在終端中輸入如下命令,構(gòu)建本地服務(wù)器:

webpack-dev-server

終端輸出信息如下圖,表示 Webpack 構(gòu)建的本地服務(wù)器已啟動.

終端輸出信息

在瀏覽器中打開 http://localhost:9000/ 就可以看到像之前一樣的問候語頁面.

結(jié)果

也可以使用 npm 更快捷的執(zhí)行任務(wù),編輯 webpack-demo 文件夾下的 package.json 文件 scripts 選項.

// package.json

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "webpack",
        "dev": "webpack-dev-server --devtool eval --progress --content-base build"
    },
    "author": "",
    "license": "ISC"
}

在終端中執(zhí)行 npm run dev 命令,輸出信息如下圖,一樣可以啟動的本地服務(wù)器.

image.png

Ctrl + C 即可退出本地服務(wù)器.

一切皆模塊

Webpack 有一個不可不說的優(yōu)點,它把所有的文件都可以當做模塊處理攒发,包括你的 JavaScript 代碼调塌,也包括 CSS 和 fonts 以及圖片等等,只要通過合適的 Loaders惠猿,它們都可以被當做模塊被處理.

Loaders

webpack 可以使用 loader 來預(yù)處理文件羔砾。這允許你打包除 JavaScript 之外的任何靜態(tài)資源.通過使用不同的 loader,Webpack 通過調(diào)用外部的腳本或工具可以對任何靜態(tài)資源進行處理紊扬,比如說分析 JSON 文件并把它轉(zhuǎn)換為 JavaScript 文件蜒茄,或者說把 ES6 / ES7 的 JS 文件轉(zhuǎn)換為現(xiàn)代瀏覽器可以識別的 JS 文件.對 React 開發(fā)而言,合適的 Loaders 可以把 React 的 JSX 文件轉(zhuǎn)換為 JS 文件.

Loaders 需要單獨安裝并且需要 在webpack.config.js 下的 modules 關(guān)鍵字下進行配置餐屎,Loaders 的配置選項包括以下幾方面:

  • test:一個匹配 Loaders 所處理的文件的拓展名的正則表達式(必須)
  • loader:loader 的名稱(必須)
  • include/exclude: 手動添加必須處理的文件/文件夾,或屏蔽不需要處理的文件/文件夾(可選)
  • query:為 Loaders 提供額外的設(shè)置選項(可選)

繼續(xù)動手實踐,修改 app 文件夾下的 Greeter.js 文件,把問候消息放在一個單獨的 JSON 文件里,通過 loader 的使 Greeter.js 可以讀取該 JSON 文件.

1. 在 app 文件夾下創(chuàng)建 config.json 文件,并輸入如下代碼:

//config.json

{
    "greetText": "Hi there and greetings from JSON!"
}

2. 編輯 app 文件夾下的 Greeter.js 文件,修改后如下:

// Greeter.js

var config = require('./config.json');

module.exports = function() {
    var greet = document.createElement('div');
    greet.textContent = config.greetText;
    return greet;
}

3. 安裝支持導(dǎo)入 JSON 文件的 json-loader .由于 webpack 2.× 默認支持導(dǎo)入 JSON 文件.如果你使用自定義文件擴展名檀葛,可能仍然需要使用此 loader.在終端中運行如下命令,安裝 json-loader 到你的項目中.

//安裝到你的項目中
npm install --save-dev json-loader

因為 json-loader 安裝到你的項目目錄里了,所以 webpack-demo 項目下會新增一個 node_modules 文件夾用于存放安裝的 json-loader.此時的項目結(jié)構(gòu)如下:

項目結(jié)構(gòu)

4. 編輯 webpack.config.js 文件配置 modules 選項,添加 json-loader,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }]
    }
}

在終端中輸入 npm start 重新編譯打包,再在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明 json-loader 配置成功了.

index.html

Babel

Babel 其實是一個編譯 JavaScript 的平臺,它的強大之處表現(xiàn)在可以通過編譯幫你達到以下目的:

  • 把 ES6 / ES7 標準的 JavaScript 轉(zhuǎn)化為瀏覽器能夠解析的 ES5 標準的 JavaScript.
  • 使用基于 JavaScript 進行了拓展的語言腹缩,比如 React 的 JSX.

Babel的安裝與配置

Babel 其實是幾個模塊化的包屿聋,其核心功能位于稱為 babel-core 的 npm 包中,不過 Webpack 把它們整合在一起使用藏鹊,但是對于每一個你需要的功能或拓展润讥,你都需要安裝單獨的包.用得最多的是解析 ES6 的 babel-preset-es2015 包和解析 JSX 的 babel-preset-react 包.

先來安裝這些依賴包,輸入如下命令,把這些依賴包安裝到你的項目中.

// 利用 npm 一次性安裝多個依賴模塊,模塊之間用空格隔開
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

//安裝 React 和 React-DOM
npm install --save react react-dom

編輯 webpack.config.js 文件配置 modules 選項,添加 Babel 配置,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader",
            query: {
                presets: ['es2015', 'react']
            }
        }]
    }
}

使用 ES6 的語法盘寡,更新 app 文件夾下的 Greeter.js 文件,并返回一個 React 組件,修改后的代碼如下:

// Greeter.js

import React, { Component } from 'react';
import config from './config.json';

class Greeter extends Component {
    render() {
        return (<div> { config.greetText } </div>);
        }
    }

    export default Greeter;

使用 ES6 的模塊定義和渲染 Greeter 模塊,修改 app 文件夾下的 main.js 文件,修改后的代碼如下:

// main.js

import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

render(<Greeter />, document.getElementById('root'));

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)成功配置了 Babel.

index.html

Babel的配置選項

Babel 其實可以完全在 webpack.config.js 文件中進行配置楚殿,但是考慮到 babel 具有非常多的配置選項,在單一的 webpack.config.js 文件中進行配置往往使得這個文件顯得太復(fù)雜竿痰,因此一些開發(fā)者支持把 babel 的配置選項放在一個單獨的名為 ".babelrc" 的配置文件中脆粥。我們現(xiàn)在的 babel 的配置并不算復(fù)雜,不過之后我們會再加一些東西影涉,因此現(xiàn)在我們就提取出相關(guān)部分变隔,分兩個配置文件進行配置, Webpack 會自動調(diào)用 .babelrc 里的 babel 配置選項.

編輯 webpack.config.js 文件配置 modules 選項,添加 Babel 配置,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }]
    }
}

在 webpack-demo 文件夾下新建 .babelrc 文件,添加如下代碼:

// .babelrc

{
    "presets": ['es2015', 'react']
}

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)成功配置了 Babel.

index.html

CSS

Webpack 提供兩個工具處理樣式表,css-loader 和 style-loader.

  • css-loader 使你能夠使用類似 @import 和 url(...) 的方法實現(xiàn) require() 的功能
  • style-loader 將所有的計算后的樣式加入頁面中

二者組合在一起使你能夠把樣式表嵌入 Webpack 打包后的 JS 文件中蟹倾。

先來安裝 css-loader, style-loader,輸入如下命令,把這些依賴包安裝到你的項目中.

npm install --save-dev style-loader css-loader

編輯 webpack.config.js 文件配置 modules 選項,添加處理樣式表配置,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader' //添加對樣式表的處理,感嘆號的作用在于使同一文件能夠使用不同類型的 loader
        }]
    }
}

接下來匣缘,在 app 文件夾里創(chuàng)建一個名為 main.css 的文件,在文件中添加如下代碼,對一些元素設(shè)置樣式.

// main.css

html {
    box-sizing: border-box;
    -ms-text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%;
}

*,
*:before,
*:after {
    box-sizing: inherit;
}

body {
    margin: 0;
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1,
h2,
h3,
h4,
h5,
h6,
p,
ul {
    margin: 0;
    padding: 0;
}

Webpack 只有單一的入口鲜棠,其它的模塊需要通過 import, require, url 等導(dǎo)入相關(guān)位置肌厨,為了讓 Webpack 能找到 main.css 文件,我們把它導(dǎo)入 app 文件夾下的 main.js 中.修改 app 文件夾下的 main.js 文件,修改后的代碼如下:

// main.js

import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';
import './main.css'; //導(dǎo)入css文件

render(<Greeter/>, document.getElementById('root'));

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)配置成功了.

index.html

通常情況下豁陆,css 會和 js 打包到同一個文件中夏哭,并不會打包為一個單獨的 css 文件,不過通過合適的配置 Webpack 也可以把 css 打包為單獨的文件的献联。
不過這也只是 Webpack 把 css 當做模塊而已竖配,繼續(xù)看一個真的 CSS 模塊的實踐.

CSS module

在過去的一些年里何址,JavaScript 通過一些新的語言特性、更好的工具进胯、更好的實踐方法(比如說模塊化)發(fā)展得非常迅速用爪。模塊使得開發(fā)者把復(fù)雜的代碼轉(zhuǎn)化為小的、干凈的胁镐、依賴聲明明確的單元偎血,且基于優(yōu)化工具,依賴管理和加載管理可以自動完成盯漂。

不過前端的另外一部分颇玷,CSS 的發(fā)展就相對慢一些,大多的樣式表卻依舊是巨大且充滿了全局類名就缆,這使得維護和修改都非常困難和復(fù)雜帖渠。

CSS modules 的技術(shù)就能夠把 JS 的模塊化思想帶入 CSS 中來,通過 CSS 模塊竭宰,所有的類名空郊,動畫名默認都只作用于當前模塊.

Webpack 從一開始就對 CSS 模塊化提供了支持,在 CSS loader 中進行配置后切揭,你所需要做的一切就是把 modules 傳遞到需要的地方狞甚,然后就可以直接把 CSS 的類名傳遞到組件的代碼中,且這樣做只對當前組件有效廓旬,不必擔(dān)心在不同的模塊中具有相同的類名可能會造成的問題哼审。

編輯 webpack.config.js 文件配置 modules 選項,添加處理樣式表配置,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules' //跟前面相比就在后面加上了 ?modules
        }]
    }
}

接下來,在 app 文件夾里創(chuàng)建一個名為 Greeter.css 的文件孕豹,在文件中添加如下代碼,對一些元素設(shè)置樣式.

// Greeter.css

.root {
    background-color: #eee;
    padding: 10px;
    border: 3px solid #ccc;
}

導(dǎo)入 .root 到 Greeter.js 中,修改 app 文件夾下的 Greeter.js 文件,修改后的代碼如下:

// Greeter.js

import React, { Component } from 'react';
import config from './config.json';
import styles from './Greeter.css'; //導(dǎo)入 .root 到 Greeter.js 中

class Greeter extends Component {
    render() {
        return ( <div className={styles.root}> { config.greetText } </div>);
        }
    }

    export default Greeter;

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)配置成功了.

index.html

CSS modules 也是一個很大的主題棺蛛,有興趣的話可以去官方文檔查看更多消息.下面兩篇文章也可以看看:

CSS 預(yù)處理器

CSS 預(yù)處理器可以將 SASS、LESS 文件轉(zhuǎn)化為瀏覽器可識別的 CSS 文件,以下是常用的CSS 預(yù)處理器 loaders.

  • Less Loader
  • Sass Loader
  • Stylus Loader

其實也存在一個 CSS 的處理平臺 PostCSS巩步,它可以幫助你的 CSS 實現(xiàn)更多的功能,可以看看<<PostCSS 是個什么鬼東西桦踊?>>.

舉例來說如何使用 PostCSS椅野,我們使用 PostCSS 來為 CSS 代碼自動添加適應(yīng)不同瀏覽器,不同版本的 CSS 前綴。首先安裝 postcss-loader 和 autoprefixer(自動添加前綴的插件),安裝到你的項目中.

npm install --save-dev postcss-loader autoprefixer

編輯 webpack.config.js 文件配置 modules 選項,添加 postcss-loader 處理樣式表配置,編輯后的文件如下:

// webpack.config.js

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules!postcss-loader' //跟前面相比就在后面加上了 !postcss-loader
        }]
    }
}

在 webpack-demo 文件夾下新建 postcss.config.js 文件,添加如下代碼:

// postcss.config.js

module.exports = {
    plugins: [
        //調(diào)用autoprefixer插件,還可以配置選項添加需要兼容的瀏覽器版本.
        require("autoprefixer")({ browsers: ['ie>=8', '>1% in CN'] })
    ]
}

現(xiàn)在你寫的樣式會自動根據(jù) Can i use 里的數(shù)據(jù)添加不同前綴了.在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)成功配置了 PostCSS.

index.html

插件(Plugins)

插件(Plugins)是用來拓展 Webpack 功能的籍胯,它會在整個構(gòu)建過程中生效竟闪,執(zhí)行相關(guān)的任務(wù)。
Loaders 和 Plugins 常常被弄混杖狼,但是他們其實是完全不同的東西炼蛤,可以這么說,Loaders 是在打包構(gòu)建過程中用來處理源文件的(JSX蝶涩,Scss理朋,Less..)絮识,一次處理一個;插件并不直接操作單個文件,它直接對整個構(gòu)建過程其作用嗽上。

Webpack 有很多內(nèi)置插件次舌,同時也有很多第三方插件,可以讓我們完成更加豐富的功能兽愤。

使用插件的方法

要使用某個插件彼念,我們需要通過 npm 安裝它,然后要做的就是在 Webpack 配置中的 Plugins 關(guān)鍵字部分添加該插件的一個實例.

編輯 webpack.config.js 文件配置 Plugins 選項,添加一個實現(xiàn)版權(quán)聲明的 BannerPlugin 插件,BannerPlugin 是內(nèi)置插件不需要使用 npm 安裝.編輯后的文件如下:

// webpack.config.js

var webpack = require("webpack");
module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/public/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules!postcss-loader' //跟前面相比就在后面加上了 !postcss-loader
        }]
    },
    plugins: [
        new webpack.BannerPlugin("Copyright Flying Unicorns inc.")//在這個數(shù)組中new一個實例就可以了
    ]
}

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

在瀏覽器中打開 public 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)成功配置了 BannerPlugin 插件.

index.html

常用插件

給大家推薦幾個常用的插件

HtmlWebpackPlugin

這個插件的作用是依據(jù)一個簡單的模板浅萧,幫你生成最終的 html 文件逐沙,這個文件中自動引用了你打包后的 JS 文件。每次編譯都在文件名中插入一個不同的哈希值洼畅。

安裝 HtmlWebpackPlugin 到你的項目中
npm install --save-dev html-webpack-plugin

在使用 HtmlWebpackPlugin 之前,需要對 webpack-demo 項目結(jié)構(gòu)做一些改變.

1. 移除 public 文件夾.

2. 在 app 目錄下吩案,創(chuàng)建一個文件名為 index.tmpl.html 模板文件,在編譯過程中,HtmlWebpackPlugin 插件會依據(jù)此模板生成最終的 html 頁面,會自動添加所依賴的 css土思、 js务热、favicon等文件.index.tmpl.html 模板文件代碼如下:

// index.tmpl.html

<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <title>webpack-demo</title>
</head>

<body>
    <div id="root"></div>
</body>

</html>

3. 在 webpack-demo 文件夾下新建一個 build 文件夾用來存放最終的輸出文件.

4. 編輯 webpack.config.js 文件配置 Plugins 選項,添加 HtmlWebpackPlugin 插件,修改 output 選項.編輯后的文件如下:

// webpack.config.js

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/build/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        contentBase: "./public",
        port: "9000",
        inline: true,
        historyApiFallback: true,
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules!postcss-loader' //跟前面相比就在后面加上了 !postcss-loader
        }]
    },
    plugins: [
        new webpack.BannerPlugin("Copyright Flying Unicorns inc."), //在這個數(shù)組中new一個實例就可以了
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new一個插件的實例,并傳入相關(guān)的參數(shù)
        })
    ]
}

此時項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

在終端中運行 npm start 命令重新編譯打包,終端輸出信息如下:

終端輸出信息

此時項目結(jié)構(gòu)已經(jīng)發(fā)生改變,build 文件夾下存放了最終的輸出的文件,項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

在瀏覽器中打開 build 文件夾下的 index.html 文件,如果看到和下圖一樣的,就說明已經(jīng)成功配置了 HtmlWebpackPlugin 插件.

index.html

Hot Module Replacement

Hot Module Replacement(HMR)也是 Webpack 里很有用的一個插件己儒,它允許你在修改組件代碼后崎岂,自動刷新實時預(yù)覽修改后的效果。
在 Webpack 中使用 HMR 也很簡單闪湾,只需要做兩項配置.

  • 在 Webpack 配置文件中添加 HMR 插件
  • 在 Webpack Dev Server 中添加 hot 參數(shù)

不過配置完這些后冲甘,JS 模塊其實還是不能自動熱加載的,還需要在你的 JS 模塊中執(zhí)行一個 Webpack 提供的 API 才能實現(xiàn)熱加載途样,雖然這個 API 不難使用江醇,但是如果是 React 模塊,使用我們已經(jīng)熟悉的 Babel 可以更方便的實現(xiàn)功能熱加載何暇。

整理下思路陶夜,具體實現(xiàn)方法如下

  • Babel 和 Webpack 是獨立的工具,二者可以一起工作,二者都可以通過插件拓展功能.
  • HMR 是一個 Webpack 插件,它讓你能瀏覽器中實時觀察模塊修改后的效果,但是如果你想讓它工作裆站,需要對模塊進行額外的配額.
  • Babel 有一個叫做 react-transform-hrm 的插件条辟,可以在不同 React 模塊進行額外的配置下讓 HMR 正常工作.

編輯 webpack.config.js 文件配置 Plugins / devServer 選項,添加 Hot Module Replacement 插件.編輯后的文件如下:

// webpack.config.js

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/build/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        port: "9000",
        inline: true,
        historyApiFallback: true,
        hot: true
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules!postcss-loader' //跟前面相比就在后面加上了 !postcss-loader
        }]
    },
    plugins: [
        new webpack.BannerPlugin("Copyright Flying Unicorns inc."), //在這個數(shù)組中new一個實例就可以了
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new一個插件的實例,并傳入相關(guān)的參數(shù)
        }),
        new webpack.HotModuleReplacementPlugin() //熱加載插件
    ]
}

安裝 react-transform-hmr 插件

npm install --save-dev babel-plugin-react-transform react-transform-hmr

編輯在 webpack-demo 文件夾下的 .babelrc 文件,編輯后的文件如下:

// .babelrc

{
  "presets": ["react", "es2015"],
  "env": {
    "development": {
    "plugins": [["react-transform", {
       "transforms": [{
         "transform": "react-transform-hmr",
         "imports": ["react"],
         "locals": ["module"]
       }]
     }]]
    }
  }
}

編輯 webpack-demo 文件夾下的 package.json 文件 scripts 選項,添加 --hot 選項開啟代碼熱替換.

// package.json

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "webpack",
        "dev": "webpack-dev-server --devtool eval --progress --content-base build --hot"
    },
    "author": "",
    "license": "ISC"
}

在終端中執(zhí)行 npm run dev 命令,輸出信息如下圖,一樣可以啟動自動熱加載.

終端輸出信息

在瀏覽器中打開 http://localhost:9000/ 就可以看到像之前一樣的問候語頁面.

結(jié)果

現(xiàn)在當你使用 React 時宏胯,就可以熱加載模塊了.按 Ctrl + C 即可退出自動熱加載.

產(chǎn)品階段的構(gòu)建

我們已經(jīng)使用 Webpack 構(gòu)建了一個完整的開發(fā)環(huán)境.但是在產(chǎn)品階段,可能還需要對打包的文件進行額外的處理羽嫡,比如說優(yōu)化、壓縮肩袍、緩存以及分離 CSS 和 JS.

對于復(fù)雜的項目來說杭棵,需要復(fù)雜的配置,這時候分解配置文件為多個小的文件可以使得事情井井有條氛赐,以 webpack-demo 項目來說魂爪,我們在 webpack-demo 文件夾下創(chuàng)建一個名為 webpack.production.config.js 的文件先舷,在里面加上基本的配置代碼,如下:

// webpack.production.config.js

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/build/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules!postcss-loader' //跟前面相比就在后面加上了 !postcss-loader
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new一個插件的實例,并傳入相關(guān)的參數(shù)
        })
    ]
}

編輯 webpack-demo 文件夾下的 package.json 文件 scripts 選項,添加 build 選項,編輯后的文件如下:

// package.json

{
    "name": "webpack-demo",
    "version": "1.0.0",
    "description": "",
    "scripts": {
        "start": "webpack",
        "dev": "webpack-dev-server --devtool eval --progress --content-base build --hot",
        "build": "webpack --config ./webpack.production.config.js --progress"
    },
    "author": "",
    "license": "ISC"
}

在終端中執(zhí)行 npm run build 命令,輸出信息如下圖:

輸出信息

說明分解配置文件為多個小的文件成功了.

優(yōu)化插件

Webpack 提供了一些在發(fā)布階段非常有用的優(yōu)化插件甫窟,它們大多來自于 Webpack 社區(qū)密浑,可以通過 npm 安裝,通過以下插件可以完成產(chǎn)品發(fā)布階段所需的功能.

  • OccurrenceOrderPlugin: 為組件分配 ID粗井,通過這個插件 Webpack 可以分析和優(yōu)先考慮使用最多的模塊尔破,并為它們分配最小的 ID.
  • UglifyJsPlugin:壓縮JS代碼.
  • ExtractTextPlugin:分離 CSS 和 JS 文件.

我們來看看如何使用它們,OccurrenceOrderPlugin 和 UglifyJS plugins 都是內(nèi)置插件浇衬,我們只需要安裝 ExtractTextPlugin 插件.

安裝 ExtractTextPlugin 插件

npm install --save-dev extract-text-webpack-plugin

編輯 webpack.config.js 文件配置 Plugins 選項,添加這三個插件,因為要分離 css 所以還要配置 module 下的 loaders 選項.編輯后的文件如下:

// webpack.config.js

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/build/", //存放打包后文件的地方路徑
        filename: "bundle.js" //打包后的文件名
    },
    devServer: {
        port: "9000",
        inline: true,
        historyApiFallback: true,
        hot: true
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader?modules!postcss-loader"
            })
        }]
    },
    plugins: [
        new webpack.BannerPlugin("Copyright Flying Unicorns inc."), //在這個數(shù)組中new一個實例就可以了
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new一個插件的實例懒构,并傳入相關(guān)的參數(shù)
        }),
        new webpack.HotModuleReplacementPlugin(), //熱加載插件
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
    ]
}

在終端中執(zhí)行 npm start 命令,輸出信息如下圖:

輸出信息

此時項目結(jié)構(gòu)已經(jīng)發(fā)生改變,build 文件夾下多出了抽離出來的 style.css 文件還有對應(yīng)的 style.css.map 文件,項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

如果你打開 build 文件夾下的 bundle.js 文件,就可以看到 bundle.js 文件內(nèi)容已經(jīng)被壓縮處理了.

說明這三個插件已經(jīng)配置成功了.

緩存

為了加快加載速度,合理的利用緩存是必不可少的.使用緩存的最好方法是保證文件名和文件內(nèi)容是匹配的.內(nèi)容改變,名稱也相應(yīng)改變.

Webpack 可以把一個哈希值添加到打包文件的文件名中,添加特殊的字符串混合體([name], [id] and [hash])到輸出文件名前,便于修改 BUG 以后,對應(yīng)更新用戶本地的緩存文件.

編輯 webpack.config.js 文件修改 output / plugins 選項.編輯后的文件如下:

// webpack.config.js

var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    devtool: "source-map", //配置生成 Source Maps 的選項
    entry: __dirname + "/app/main.js", //入口文件路徑
    output: {
        path: __dirname + "/build/", //存放打包后文件的地方路徑
        filename: "[name]-[hash].js" //打包后的文件名
    },
    devServer: {
        port: "9000",
        inline: true,
        historyApiFallback: true,
        hot: true
    },
    module: {
        loaders: [{
            test: /\.json$/,
            loader: "json-loader"
        }, {
            test: /\.js$/,
            exclude: /node_modules/, //編譯打包時需要排除 node_modules 文件夾
            loader: "babel-loader"
        }, {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader?modules!postcss-loader"
            })
        }]
    },
    plugins: [
        new webpack.BannerPlugin("Copyright Flying Unicorns inc."), //在這個數(shù)組中new一個實例就可以了
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new一個插件的實例耘擂,并傳入相關(guān)的參數(shù)
        }),
        new webpack.HotModuleReplacementPlugin(), //熱加載插件
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("[name]-[hash].css")
    ]
}

在終端中執(zhí)行 npm start 命令,輸出信息如下圖:

輸出信息

此時項目 build 文件夾下的 main.css 和 main.js 文件都對應(yīng)的加上了哈希值.項目結(jié)構(gòu)如下圖所示:

項目結(jié)構(gòu)

如果你打開 build 文件夾下的 index.html 文件,就可以看到引用的 css胆剧、js 文件名也對應(yīng)發(fā)生了改變,這樣修改 BUG 以后,也能對應(yīng)更新用戶本地的緩存文件.

進階,永不止步

其實到這里我的這篇 Webpack 2.x 的入門實戰(zhàn)已經(jīng)完結(jié)了!但這也只是個入門而已!在實際項目中運用還是不夠的,還有很多細節(jié)我并沒深入講,所以大家還想進階的話建議好好去看看 webpack-china 的文檔.

另外實戰(zhàn)項目 webpack-demo 的源碼,我已經(jīng)放到 Github 上去了,歡迎大家提意見.

還有一點我覺得很重要,要學(xué)會看控制臺輸出信息,能夠看控制臺輸出信息解決的問題,就不要上 Google 搜了!

鳴謝

這篇 Webpack 2.x 的入門實戰(zhàn)是基于 zhangwang<<入門Webpack,看這篇就夠了>> 寫出來的,是我學(xué)習(xí) Webpack 的實戰(zhàn)記錄.特別感謝 zhangwang 付出,如果你覺得這篇文章對你有幫助,請轉(zhuǎn)到 zhangwang 為他點個贊.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醉冤,一起剝皮案震驚了整個濱河市秩霍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚁阳,老刑警劉巖铃绒,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異螺捐,居然都是意外死亡颠悬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門定血,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赔癌,“玉大人,你說我怎么就攤上這事澜沟≡制保” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵茫虽,是天一觀的道長刊苍。 經(jīng)常有香客問我,道長席噩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任贤壁,我火速辦了婚禮悼枢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘脾拆。我一直安慰自己馒索,他們只是感情好莹妒,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绰上,像睡著了一般旨怠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜈块,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天鉴腻,我揣著相機與錄音,去河邊找鬼百揭。 笑死爽哎,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的器一。 我是一名探鬼主播课锌,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祈秕!你這毒婦竟也來了渺贤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎进宝,沒想到半個月后坝橡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡述雾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了兼丰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玻孟。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鳍征,靈堂內(nèi)的尸體忽然破棺而出黍翎,到底是詐尸還是另有隱情,我是刑警寧澤艳丛,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布匣掸,位于F島的核電站,受9級特大地震影響氮双,放射性物質(zhì)發(fā)生泄漏碰酝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一戴差、第九天 我趴在偏房一處隱蔽的房頂上張望送爸。 院中可真熱鬧,春花似錦、人聲如沸袭厂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纹磺。三九已至帖烘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橄杨,已是汗流浹背秘症。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留讥珍,地道東北人历极。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像衷佃,于是被迫代替她去往敵國和親趟卸。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 無意中看到zhangwnag大佬分享的webpack教程感覺受益匪淺氏义,特此分享以備自己日后查看锄列,也希望更多的人看到...
    小小字符閱讀 8,140評論 7 35
  • GitChat技術(shù)雜談 前言 本文較長,為了節(jié)省你的閱讀時間惯悠,在文前列寫作思路如下: 什么是 webpack邻邮,它要...
    蕭玄辭閱讀 12,671評論 7 110
  • 在現(xiàn)在的前端開發(fā)中,前后端分離克婶、模塊化開發(fā)筒严、版本控制、文件合并與壓縮情萤、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,431評論 1 32
  • 1. 新建一個文件夾,命名為 webpack-cli , webpack-cli 就是你的項目名,項目名建議使用小...
    魯大師666閱讀 1,463評論 1 3
  • 公休去哪里玩把纪堋?你幾月份休息敖畹骸娶视?我們把護照、通行證都辦了吧睁宰!最近我們的話題中多了“旅行”兩個字肪获。 自從前段時間最流...
    有一只小熊閱讀 247評論 0 1