本文是混子前端以前在學習 webpack 時整理的說明文件 有些枯燥 但整理的很詳細,其中代碼模塊我已圖文備註說明,若是你剛開始準備學習 webpack 那本文對你幫助很大,必定要按照文字走徹底流程
webpack基本介紹
webpack: 給js準備的一個打包工具,能夠把不少模塊打包成不多的靜態文件,有一個本身的特性:代碼分割 (code splitting),還有一個loaders的概念,模塊是經過loaders處理各類文件,不管js是用 commonJS、AMD、ES六、CSS、Images、JSON、Coffeescript、LESS... 均可以用loaders 處理,甚至還能夠是本身定義的一些文件,如:.vue、.JSX文件均可以經過 loaders 處理css
代碼分割: 可使項目加載過程當中只去加載一些當時只須要的部分文件
webpack官方:就是一個模塊打包器,下圖左邊箭頭表示文件之間依賴關係的模塊羣,這樣的模塊羣經過 webpack 打包以後,對依賴進行處理把他打包成能夠直接運行的 js/css/圖片 文件
![](http://static.javashuo.com/static/loading.gif)
webpack目標:
- 會切分依賴樹,會把依賴樹切分不一樣代碼塊裏,而後按需加載依賴,和前端懶加載概念類似
- 保持初始化加載時間更少
- 任何靜態資源均可以視爲一個模塊在項目中引用,在開發中起到不少便利,整合第三方類庫,把第三方類庫視作模塊在項目中引用
- 能夠在整個打包過程當中,每一步均可以自定義去作事情
和其餘打包工具不一樣 gulp/grount
- code Splitting 代碼分割
- loaders
- 插件系統,模塊熱更新 plugin system:在開發過程當中提升開發和調試效率
核心思想:
打包原理:
bundle.js 是以模塊 id 爲記號,經過函數把各個文件 依賴封裝 達成分割效果
webpack安裝和命令行
> mkdir webpack-test //建立webpack-test文件夾
> npm init //初始化項目,建立package.json文件
> npm install webpack@3.0.0 --save-dev //安裝3.0版本webpack,由於4.0版本直接打包會報錯,比較嚴格
> 建立hello.js 和 world.js,用commonJS規範在hello.js require world.js
> webpack hello.js hello.bundle.js //打包hello.js文件
觀察hello.bundle.js:
![](http://static.javashuo.com/static/loading.gif)
html
能夠看到world代碼被打包進來了,編號是 1,寫在 hello.js 中的 require 被替換成webpack_require,webpack用這種方式去尋找依賴,把文件打包到一塊兒,這是簡單工做方式
前端
> 繼續建立 style.css 文件,在 hello.js 中 require style.css (不深究爲何),執行打包命令:webpack hello.js hello.bundle.js 開始報錯,提示沒有安裝 css loader,由於他不支持打包 css類型,若是打包 css 文件須要安裝 css loader
> npm install css-loader style-loader --save-dev
> 執行打包命令仍是會報錯,由於在 hello.js 中 require style.css 沒有執行loader,須要寫成require('css-loader!./style.css'),意思是:在引用style.css文件前必須通過css-loader處理,繼續執行打包命令,沒有報錯
> 建立 index.html 引用hello.js文件,而且在 style.css 中給 body 添加 background 屬性,發現執行打包命令後顏色沒有效果,要想顏色有效果要結果style-loader,在hello.js中改成require('style-loader!css-loader!./style.css')
能夠看出css-loader讓webpack去處理css文件,style-loader經過css-loader處理完的文件,把處理完的文件新建一個style標籤插入到html head裏面
> 若是在代碼裏每次 require css 都須要寫一長串的話 style-loader!css-loader! 的話會很麻煩,也能夠用打包命令:vue
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader'react
用到了webpack中 --module-bind 的參數,至關於把這個模塊綁定:若是是css文件就先交給css-loader,css-loader以前要style-loader
webpack
> 若是每次改變都須要打包的話,會很麻煩,能夠用--watch參數監聽:
webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watches6
> 除了--watch還有一些其餘參數,如:
一、--progress : 看到打包的百分比;web
二、 --display-modules:看到打包的模塊和用到的loader列出來;npm
三、--display-reasons:打包 模塊的緣由列舉出來json
創建項目的webpack配置文件
創建 webpack.config.js 緣由:若是直接使用 webpack 命令,會直接在項目根目錄尋找webpack.config.js 做爲默認配置去運行,這時不須要指定任何參數,會直接讀取 config 裏面的內容,也可使用 --config 指定其餘配置文件
即:執行 webpack 會去項目目錄找 webpack.config.js 文件,若是配置文件不叫這個名字 (假如修改成webpack.dev.config.js),能夠執行 webpack --config webpack.dev.config.js,也可生效
若是想在webpack命令行中加入一些參數,能夠藉助 package.json 中 script 屬性
![](http://static.javashuo.com/static/loading.gif)
webpack配置的entry和output
一、entry 打包2個平行的js文件能夠寫成數組模式
![](http://static.javashuo.com/static/loading.gif)
打包後的 bundle.js 文件
![](http://static.javashuo.com/static/loading.gif)
這個0模塊把兩個不相干的模塊,require 打包到一塊兒,這樣就能夠在開發中使用
二、在多頁面應用程序,能夠用到entry爲對象的形式,對象的key是 chunk name,value 是entry,根據不一樣頁面分配不一樣的 chunk,若是 entry 的 objcet 是多餘一個的,那打包好的文件就不能夠是一個了,這時候就要修改 output,在 output 中修改 filename 屬性,這裏若是指定了 hash,以下圖:![](http://static.javashuo.com/static/loading.gif)
打包後的多個文件 hash 值都同樣,因此引出了 chunk-hash,以下圖:![](http://static.javashuo.com/static/loading.gif)
若是每次打包生成的惟一加密(md5)後 chunk-name不同,那 html 文件中引入的也不同了,因此這裏要加入插件
html-webpack-plugin,在項目中 npm 安裝,在 webpack.config.js 中配置,以下圖:
![](http://static.javashuo.com/static/loading.gif)
這時候運行 npm run webpack,會生成打包好 帶有 hash 值的 main.js 和 a.js 文件,還有新的html 文件引入了帶有 hash 值的壓縮文件,以下圖:
![](http://static.javashuo.com/static/loading.gif)
插件生成的 index.html 和項目根目錄的 index.html 沒有任何關係,這不知足需求。若是以根目錄index.html去生成dist下index.html,就要在 webpack.config.js 中繼續操做
![](http://static.javashuo.com/static/loading.gif)
這時就能夠把根目錄下 index.html 中 script src 標籤刪掉,打包後的 index.html 會自動引入壓縮並帶有 hash 值的 js 文件,這時候發現一個問題,全部壓縮好的文件都在dist/js下,這和實際生產不符,實際須要 index.html 在 dist/js 目錄外的,還要去修改 webpack.config.js,將不是 js 文件都建立到 dist 目錄,將js文件 filename 指定相對路徑
![](http://static.javashuo.com/static/loading.gif)
打包後文件結構以下圖:
![](http://static.javashuo.com/static/loading.gif)
除了 template 還有一些其餘參數:![](http://static.javashuo.com/static/loading.gif)
如何作到在 webpack.config.js 中修改 index.html 文件 title![](http://static.javashuo.com/static/loading.gif)
index.html中:
![](http://static.javashuo.com/static/loading.gif)
還能獲取到哪些參數:
![](http://static.javashuo.com/static/loading.gif)
index.html 中:
![](http://static.javashuo.com/static/loading.gif)
打包編譯後爲:
![](http://static.javashuo.com/static/loading.gif)
究竟能從 htmlWebpackPlugin 取到哪些信息?
這時候能夠對 htmlWebpackPlugin進行遍歷,由於相似於模版文件引擎寫法,能夠直接編寫:
![](http://static.javashuo.com/static/loading.gif)
在打包後生成的 index.html 中能夠看到:
![](http://static.javashuo.com/static/loading.gif)
繼續遍歷 files 和 options 能夠拿到不少配置信息,不一一介紹了,能夠去 npmjs.com 搜索html-wekpack.plugin 進行查看
![](http://static.javashuo.com/static/loading.gif)
繼續探索,假如想把一部分 js 放到 index 的 head 標籤裏,一部分想放到 body 標籤裏,只經過配置是作不到的,因此要改變模版:
一、將 webpack.config.js 中 inject 修改成 false
![](http://static.javashuo.com/static/loading.gif)
二、編寫 script 標籤 src 便可
![](http://static.javashuo.com/static/loading.gif)
繼續探索,假如打包後要上線,上線後的地址和本地的相對路徑確定不同,這時候要藉助output 新屬性:[[ publicPath ]]![](http://static.javashuo.com/static/loading.gif)
打包後前綴就變了:
![](http://static.javashuo.com/static/loading.gif)
上線要對 html 文件進行壓縮,就要用到新屬性:[[minify]] 對當前生成的html進行壓縮
![](http://static.javashuo.com/static/loading.gif)
處理多頁面應用:須要有多個頁面,須要生成多個html:
plugins是一個數組,能夠有多個,每個對應一個頁面,直接 npm run webpack 便可生成多個html,注意這裏新的參數 chunks/excludeChunks
![](http://static.javashuo.com/static/loading.gif)
若是但願把頁面性能達到極致,把一些初始化腳本直接嵌入到頁面,而不是連接的形式引入到頁面,如今全都是連接,即:script src=***,這樣能夠達到效果但會增長http請求,如今能夠把初始的代碼直接inline入到頁面,能夠大大提升運行速度,由於沒有http請求:
經過 htmlWebpackPlugin.files.chunks.main.entry 截取掉佔位符
後經過 comilation.assets[*****] 取 source() 方法,這是引用公共類庫 mian.js 的方法,a/b/c 還有屬於本身的js方法,要引入body標籤中,這時候修改 webpack.config.js 是沒有用的,要在index.html 中寫入 js 引入外部文件
![](http://static.javashuo.com/static/loading.gif)
webpack如何處理想要的資源文件
轉換es6:
npm install --save-dev babel-loader babel-core
bebel-loader: es6不斷的修訂,經過指定persets來告訴babel-loader轉換某一些特性爲咱們的js,若是指定全部的特性能夠直接用latest,怎麼指定插件呢?給loader指定參數,這裏指定lastest,而後安裝。
![](http://static.javashuo.com/static/loading.gif)
官網還提供一種方式指定 persets,能夠項目根目錄建立 .babelrc 文件,而後指定也能夠
![](http://static.javashuo.com/static/loading.gif)
還有一種方式能夠在 package.json 裏面,直接定義 babel,能夠不在配置文件裏指定
![](http://static.javashuo.com/static/loading.gif)
babel-loader 打包編譯是很慢的,官網給出新的參數
exclude:loader 的排除範圍(不明顯)
include:loader的處理範圍
![](http://static.javashuo.com/static/loading.gif)
exclude 比較慢的緣由是沒有用到絕對路徑,在項目中怎麼獲取到絕對路徑?
一、須要藉助 path 方法
![](http://static.javashuo.com/static/loading.gif)
二、path.resolve(__dirname,'相對路徑'),resolve解析
![](http://static.javashuo.com/static/loading.gif)
同理 include也是寫絕對路徑![](http://static.javashuo.com/static/loading.gif)
如何在項目裏處理css文件?
首先要在命令行中:npm install style-loader css-loader --save-dev
建立一個common.css文件,import到app.js文件中
![](http://static.javashuo.com/static/loading.gif)
在webpack.config.js中添加loaders
![](http://static.javashuo.com/static/loading.gif)
最後npm run webpack便可,接下來查看,若是有一個須要兼容性的樣式怎麼處理?假如說:display:flex要咱們手動添加前綴進行兼容,如今有一個loader去處理
npm install postcss-loader --save-dev
postcss-loader是css的一個後處理器,安裝好以後,須要繼續安裝 autoprefixer 這是給postcss的插件,是用來處理css前綴的
npm install autoprefixer --save-dev
![](http://static.javashuo.com/static/loading.gif)
這時候 npm run webpack,能夠在網頁源碼中看到生成出來兼容性的css
![](http://static.javashuo.com/static/loading.gif)
若是在 css 中使用@import一個文件,會發現display:flex沒有生成兼容性的前綴,也就是說他通過了css-loader和style-loader,沒有通過postcss-loader,處理辦法是藉助precss插件,在項目中安裝:npm install precss --save-dev
![](http://static.javashuo.com/static/loading.gif)
在 postcss-loader 添加配置便可
如何在項目裏處理less文件,先安裝 less-loader 和 less,進行配置
npm install less-loader --save-dev npm install less --save-dev
和處理css文件的配置同樣,不過多了 less-loader,一樣要處理css代碼兼容性,官方指定,postcss-loader 處理要在 less-loader 和 css-loader 中間進行,順序不能變
![](http://static.javashuo.com/static/loading.gif)
這裏若是在 less 中使用 import 寫法,能夠不用寫 require('precss'),由於 less-loader 已經幫咱們作了處理,若是使用sass做爲項目預處理器使用方法與less同樣
如何處理項目中模版文件,一般是:
一、用webpack把模版文件看成字符串處理
二、webpack把模版文件 當成已經編譯好的模版處理函數;首先安裝html-loader
npm install html-loader --save-dev
將模版js文件引入css less 及 html模版,咱們在入口app.js文件中引入html模版文件,在webpack.config.js 中添加 html-loader 語法規範便可運行
![](http://static.javashuo.com/static/loading.gif)
如今若是,模版文件不是以html結尾,而是以.tpl結尾的模版文件,那要如何處理 ?
首先要引入新的loader:
npm install ejs-loader --save-dev
而後在webpack.config.js中添加規則,讓.tpl結尾的文件用 ejs-loader 處理
![](http://static.javashuo.com/static/loading.gif)
修改模版文件(是ejs模版引擎的語法,在模版區間內能夠自由編寫js語法):
![](http://static.javashuo.com/static/loading.gif)
而後規則不變,在layer.js引用,這時tpl就不是字符串了,而是返回的函數:
![](http://static.javashuo.com/static/loading.gif)
因此在app.js中能夠進行傳參的方式對模版內name 和 arr進行定義
![](http://static.javashuo.com/static/loading.gif)
打包後頁面輸出:
![](http://static.javashuo.com/static/loading.gif)
如今比較流行的loader,好比JSX是react框架的loader,如今這個loader已經被集成到了babel,只須要進行一些設置就能夠支持JSX,如今VUE2.0也能夠經過直接寫render函數,render函數也支持JSX語法
如何處理項目中的圖片文件,分幾種狀況,
一、css中不少的background圖片
二、模版結構裏引用了img文件
三、根部index.html引用了img文件
首先
npm install file-loader --save-dev
處理第一種狀況,在 webpack.config.js 中添加 file-loader 規則:
![](http://static.javashuo.com/static/loading.gif)
當給項目增長一個對圖片的處理規則,在項目中根目錄下 index.html 相對路徑圖片的引用,仍是css背景中 相對路徑圖片引用,loader都會幫咱們處理
還有一種狀況是模版組件中引用了img文件,會在控制檯中看到index.html中img src路徑 和 css中 background url 都被替換了,但模版中的img src路徑沒有被替換,
解決辦法:
一、儘量在模版中使用絕對地址
二、能夠在src中使用${ }的形式把圖片引用進來,這時能夠在控制檯中看到圖片地址被替換了
![](http://static.javashuo.com/static/loading.gif)
圖片打包之後的輸出地址,默認放到了dist目錄下,能夠給loader添加一些參數:
![](http://static.javashuo.com/static/loading.gif)
介紹一個新的loader,npm install url-loader --save-dev,當圖片或者文件大小大於指定的limit 指定的大小,會丟給 file-loader 去處理,當小於limit設置值的時候會把圖片或者文件轉爲base64 位編碼
![](http://static.javashuo.com/static/loading.gif)
這兩種方式各有優劣:經過 http 請求載入過來的圖片,可讓瀏覽器享受一個優點就是圖片的緩存,當圖片重複性很高的時候,經過http request下次訪問會很快,利用這個緩存;若是是base64,至關於在任何地方用到這個圖片時候,在這個地方會有一份一樣大小的 base 64 編碼存在,會致使代碼體積。真正在項目中要平衡的去看。
怎麼去壓縮圖片呢?官方給出了 image-webpack-loader,最好配合 url-loader 或 file-loader一塊兒使用
這時能夠在命令窗口看到,本來18k的圖片被壓縮很小的圖片被打包進項目
注意: loader處理方式是從右到左,從下到上的,好比(老規則)
![](http://static.javashuo.com/static/loading.gif)
先調用postcss-loader 而後 css-loader 而後 style-loader
最後老規矩,歡迎點贊和糾錯,祝你們工做愉快!