六、Webpack详解学习笔记——webpack的安装、起步、配置、loader的使用、webpack中配置Vue、plugin的使用、搭建本地服务器、webpack配置的分离
一、認識webpack
- 什么是webpack?
這個webpack還真不是一兩句話可以說清楚的。 - 我們先看看官方的解釋:
At its core, webpack is a static module bundler for modern JavaScript applications. - 從本質上來講,webpack是一個現代的JavaScript應用的靜態模塊打包工具。
但是它是什么呢?用概念解釋概念,還是不清晰。
我們從兩個點來解釋上面這句話:模塊 和 打包
- 在前面學習中,我已經用了大量的篇幅解釋了為什么前端需要模塊化。
- 而且我也提到了目前使用前端模塊化的一些方案:AMD、CMD、CommonJS、ES6。
- 在ES6之前,我們要想進行模塊化開發,就必須借助于其他的工具,讓我們可以進行模塊化開發。
- 并且在通過模塊化開發完成了項目后,還需要處理模塊間的各種依賴,并且將其進行整合打包。
- 而webpack其中一個核心就是讓我們可能進行模塊化開發,并且會幫助我們處理模塊間的依賴關系。
- 而且不僅僅是JavaScript文件,我們的CSS、圖片、json文件等等在webpack中都可以被當做模塊來使用(在后續我們會看到)。
這就是webpack中模塊化的概念。
- 理解了webpack可以幫助我們進行模塊化,并且處理模塊間的各種復雜關系后,打包的概念就非常好理解了。
- 就是將webpack中的各種資源模塊進行打包合并成一個或多個包(Bundle)。
- 并且在打包的過程中,還可以對資源進行處理,比如壓縮圖片,將scss轉成css,將ES6語法轉成ES5語法,將TypeScript轉成JavaScript等等操作。
但是打包的操作似乎grunt/gulp也可以幫助我們完成,它們有什么不同呢?
和grunt/gulp的對比:
grunt/gulp的核心是Task
我們可以配置一系列的task,并且定義task要處理的事務(例如ES6、ts轉化,圖片壓縮,scss轉成css)
之后讓grunt/gulp來依次執行這些task,而且讓整個流程自動化。 所以grunt/gulp也被稱為前端自動化任務管理工具。
我們來看一個gulp的task
下面的task就是將src下面的所有js文件轉成ES5的語法。
并且最終輸出到dist文件夾中。
什么時候用grunt/gulp呢?
- 如果你的工程模塊依賴非常簡單,甚至是沒有用到模塊化的概念。
- 只需要進行簡單的合并、壓縮,就使用grunt/gulp即可。
- 但是如果整個項目使用了模塊化管理,而且相互依賴非常強,我們就可以使用更加強大的webpack了。
所以,grunt/gulp和webpack有什么不同呢?
- grunt/gulp更加強調的是前端流程的自動化,模塊化不是它的核心。
- webpack更加強調模塊化開發管理,而文件壓縮合并、預處理等功能,是他附帶的功能。
二、webpack的安裝
安裝webpack首先需要安裝Node.js,Node.js自帶了軟件包管理工具npm
查看自己的node版本:
全局安裝webpack(這里我先指定版本號3.6.0,因為vue cli2依賴該版本)
局部安裝webpack(后續才需要)
--save-dev是開發時依賴,項目打包后不需要繼續使用的。
為什么全局安裝后,還需要局部安裝呢?
- 在終端直接執行webpack命令,使用的全局安裝的webpack
- 當在package.json中定義了scripts時,其中包含了webpack命令,那么使用的是局部webpack
三、webpack的起步
3.1 準備工作
我們創建如下文件和文件夾:
文件和文件夾解析:
mathUtils.js文件中的代碼:
main.js文件中的代碼:
3.2 js文件的打包
現在的js文件中使用了模塊化的方式進行開發,他們可以直接使用嗎?
不可以。
因為如果直接在index.html引入這兩個js文件,瀏覽器并不識別其中的模塊化代碼。
另外,在真實項目中當有許多這樣的js文件時,我們一個個引用非常麻煩,并且后期非常不方便對它們進行管理。
我們應該怎么做呢?
- 使用webpack工具,對多個js文件進行打包。
- 我們知道,webpack就是一個模塊化的打包工具,所以它支持我們代碼中寫模塊化,可以對模塊化的代碼進行處理。(如何處理的,待會兒在原理中,我會講解)
- 另外,如果在處理完所有模塊之間的關系后,將多個js打包到一個js文件中,引入時就變得非常方便了。
OK,如何打包呢?
使用webpack的指令即可
注意:如果webpack是4.0.x版本以上,使用webpack ./src/main.js -o ./dist/bundle.js --mode development
3.3 使用打包后的文件
打包后會在dist文件下,生成一個bundle.js文件
文件內容有些復雜,這里暫時先不看,后續再進行分析。
bundle.js文件,是webpack處理了項目直接文件依賴后生成的一個js文件,我們只需要將這個js文件在index.html中引入即可
四、webpack的配置
4.1 入口和出口
我們考慮一下,如果每次使用webpack的命令都需要寫上入口和出口作為參數,就非常麻煩,有沒有一種方法可以將這兩個參數寫到配置中,在運行時,直接讀取呢?
當然可以,就是創建一個webpack.config.js文件
4.2 局部安裝webpack
目前,我們使用的webpack是全局的webpack,如果我們想使用局部來打包呢?
- 因為一個項目往往依賴特定的webpack版本,全局的版本可能很這個項目的webpack版本不一致,導出打包出現問題。
- 所以通常一個項目,都有自己局部的webpack。
這里我們讓局部安裝webpack3.6.0
Vue CLI3中已經升級到webpack4,但是它將配置文件隱藏了起來,所以查看起來不是很方便。
第二步,通過.\node_modules\.bin\webpack啟動webpack打包
4.3 package.json中定義啟動
但是,每次執行都敲這么一長串有沒有覺得不方便呢?
OK,我們可以在package.json的scripts中定義自己的執行腳本。
package.json中的scripts的腳本在執行時,會按照一定的順序尋找命令對應的位置。
- 首先,會尋找本地的node_modules/.bin路徑中對應的命令。
- 如果沒有找到,會去全局的環境變量中尋找。
如何執行我們的build指令呢?
五、loader的使用
5.1 什么是loader?
loader是webpack中一個非常核心的概念。
webpack用來做什么呢?
- 在我們之前的實例中,我們主要是用webpack來處理我們寫的js代碼,并且webpack會自動處理js之間相關的依賴。
- 但是,在開發中我們不僅僅有基本的js代碼處理,我們也需要加載css、圖片,也包括一些高級的將ES6轉成ES5代碼,將TypeScript轉成ES5代碼,將scss、less轉成css,將.jsx、.vue文件轉成js文件等等。
- 對于webpack本身的能力來說,對于這些轉化是不支持的。
那怎么辦呢?給webpack擴展對應的loader就可以啦。
loader使用過程:
大部分loader我們都可以在webpack的官網中找到,并且學習對應的用法。
5.2 css文件處理 - 準備工作
項目開發過程中,我們必然需要添加很多的樣式,而樣式我們往往寫到一個單獨的文件中。
在src目錄中,創建一個css文件,其中創建一個normal.css文件。
我們也可以重新組織文件的目錄結構,將零散的js文件放在一個js文件夾中。
normal.css中的代碼非常簡單,就是將body設置為red:
但是,這個時候normal.css中的樣式會生效嗎?
- 當然不會,因為我們壓根就沒有引用它。
- webpack也不可能找到它,因為我們只有一個入口,webpack會從入口開始查找其他依賴的文件。
在入口文件中引用:
重新打包,會出現如下錯誤:
這個錯誤告訴我們:加載normal.css文件必須有對應的loader。
5.3 css文件處理 – css-loader
在webpack的官方中,我們可以找到如下關于樣式的loader使用方法:
按照官方配置webpack.config.js文件
注意:配置中有一個style-loader,我們并不知道它是什么,所以可以暫時不進行配置。
重新打包項目:
但是,運行index.html,你會發現樣式并沒有生效。
原因是css-loader只負責加載css文件,但是并不負責將css具體樣式嵌入到文檔中。
這個時候,我們還需要一個style-loader幫助我們處理。
5.4 css文件處理 – style-loader
我們來安裝style-loader
注意:style-loader需要放在css-loader的前面。
疑惑:
不對吧?按照我們的邏輯,在處理css文件過程中,應該是css-loader先加載css文件,再由style-loader來進行進一步的處理,為什么會將style-loader放在前面呢?
答案:
這次因為webpack在讀取使用的loader的過程中,是按照從右向左的順序讀取的。
在瀏覽器中打開index.html頁面:
5.5 less文件處理 – 準備工作
如果我們希望在項目中使用less、scss、stylus來寫樣式,webpack是否可以幫助我們處理呢?
我們這里以less為例,其他也是一樣的。
我們還是先創建一個less文件,依然放在css文件夾中
出現了報錯信息,提示我們需要安裝less-loader
5.6 less文件處理 – less-loader
繼續在官方中查找,我們會找到less-loader相關的使用說明
首先,還是需要安裝對應的loader
注意:我們這里還安裝了less,因為webpack會使用less對less文件進行編譯
其次,修改對應的配置文件
添加一個rules選項,用于處理.less文件
執行npm run build命令,啟動webpack重新打包項目:
注意:這里如果運行失敗了,檢查下less-loader的版本,版本過高可能就會失敗!
在main.js文件中加入一行代碼:
再次執行npm run build命令,啟動webpack重新打包項目:
在瀏覽器中打開index.html文件:
5.7 圖片文件處理 – 資源準備階段
- 首先,我們在項目中加入兩張圖片:
一張較小的圖片test01.jpg(小于8kb),一張較大的圖片test02.jpeg(大于8kb)
待會兒我們會針對這兩張圖片進行不同的處理 - 我們先考慮在css樣式中引用圖片的情況,所以我更改了normal.css中的樣式:
如果我們現在直接打包,執行npm run build命令,會出現如下報錯信息:
5.8 圖片文件處理 – url-loader
訪問官方文檔:
圖片處理,我們使用url-loader來處理,依然先安裝url-loader
修改webpack.config.js配置文件:
再次執行npm run build命令,啟動webpack重新打包項目:
注意:
此處需要注意url-loader的版本,版本太高可能會出現雖然運行沒有報錯,但是index.html頁面中無法顯示圖片,版本號如下所示,修改完之后,執行npm install重新安裝,再執行npm run build命令重新打包
再次打包,運行index.html,就會發現我們的背景圖片選出了出來。
而仔細觀察,你會發現背景圖是通過base64顯示出來的
OK,這也是limit屬性的作用,當圖片小于29kb時,對圖片進行base64編碼
那么問題來了,如果大于29kb呢?我們將background的圖片改成beijing.png
這次因為大于29kb的圖片,會通過file-loader進行處理,但是我們的項目中并沒有file-loader
5.9 圖片文件處理 – file-loader
執行npm run builde出現如下報錯提示信息:
所以,我們需要安裝file-loader,執行npm install file-loader --save-dev命令,安裝file-loader:
執行npm run build命令,就會發現dist文件夾下多了一個圖片文件:
用瀏覽器打開index.html文件發現,背景圖片仍然無法正常顯示:
- 但是,我們發現圖片并沒有顯示出來,這是因為圖片使用的路徑不正確
- 默認情況下,webpack會將生成的路徑直接返回給使用者
- 但是,我們整個程序是打包在dist文件夾下的,所以這里我們需要在路徑下再添加一個dist/
當把background屬性的url中的路徑前面加上./dist/之后,發現背景圖片可以正常顯示了,說明背景圖片一開始之所以無法顯示,是路徑錯了
解決方案如下:
在webpack.config.js文件中添加publicPath:
然后重新執行npm run build命令,再次打開index.html頁面,背景圖片就能正常顯示了!
5.10 圖片文件處理 – 修改文件名稱
我們發現webpack自動幫助我們生成一個非常長的名字
- 這是一個32位hash值,目的是防止名字重復
- 但是,真實開發中,我們可能對打包的圖片名字有一定的要求
- 比如,將所有的圖片放在一個文件夾中,跟上圖片原來的名稱,同時也要防止重復
我們發現webpack自動幫助我們生成一個非常長的名字
- 這是一個32位hash值,目的是防止名字重復
- 但是,真實開發中,我們可能對打包的圖片名字有一定的要求
- 比如,將所有的圖片放在一個文件夾中,跟上圖片原來的名稱,同時也要防止重復
所以,我們可以在options中添加上如下選項:
- img:文件要打包到的文件夾
- name:獲取圖片原來的名字,放在該位置
- hash:8:為了防止圖片名稱沖突,依然使用hash,但是我們只保留8位
- ext:使用圖片原來的擴展名
5.11 ES6語法處理
如果你仔細閱讀webpack打包的js文件,發現寫的ES6語法并沒有轉成ES5,那么就意味著可能一些對ES6還不支持的瀏覽器沒有辦法很好的運行我們的代碼。
- 在前面我們說過,如果希望將ES6的語法轉成ES5,那么就需要使用babel。
- 而在webpack中,我們直接使用babel對應的loader就可以了。
配置webpack.config.js文件:
重新打包,查看bundle.js文件,發現其中的內容變成了ES5的語法
完整的package.json:
完整的webpack.config.js文件:
const path = require('path')module.exports = {entry: './src/main.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'bundle.js',publicPath: 'dist/'},module: {rules: [{test: /\.css$/i,// css-loader只負責將css文件進行加載// style-loader負責將樣式添加到DOM中// 使用多個loader時,webpack時從右向左讀取use: ["style-loader", "css-loader"],},{test: /\.less$/i,use: [{loader: "style-loader"},{loader: "css-loader"},{loader: "less-loader"},]},{test: /\.(png|jpg|gif|jpeg)$/i,use: [{loader: 'url-loader',options: {// 當加載的圖片,小于limit時,會將圖片編譯成base64字符串形式// 當加載的圖片,大于limit時,需要使用file-loader模塊進行加載limit: 28000,name: 'img/[name].[hash:8].[ext]'},},],},{test: /\.m?js$/,// exclude:排除// include:包含exclude: /(node_modules|bower_components)/,use: {loader: 'babel-loader',options: {presets: ['es2015']}}}]} }六、webpack中配置Vue
6.1 引入vue.js
后續項目中,我們會使用Vuejs進行開發,而且會以特殊的文件來組織vue的組件。
所以,下面我們來學習一下如何在我們的webpack環境中集成Vuejs
現在,我們希望在項目中使用Vuejs,那么必然需要對其有依賴,所以需要先進行安裝
注:因為我們后續是在實際項目中也會使用vue的,所以并不是開發時依賴
那么,接下來就可以按照我們之前學習的方式來使用Vue了
修改完成后,重新打包,運行程序:
- 打包過程沒有任何錯誤(因為只是多打包了一個vue的js文件而已)
- 但是運行程序,沒有出現想要的效果,而且瀏覽器中有報錯
這個錯誤說的是我們使用的是runtime-only版本的Vue,什么意思呢?
這里我只說解決方案:Vue不同版本構建,后續我具體講解runtime-only和runtime-compiler的區別。
所以我們修改webpack的配置,添加如下內容即可:
webpack.config.js文件:
正常運行之后,我們來考慮另外一個問題:
- 如果我們希望將data中的數據顯示在界面中,就必須是修改index.html
- 如果我們后面自定義了組件,也必須修改index.html來使用組件
- 但是html模板在之后的開發中,我并不希望手動的來頻繁修改,是否可以做到呢?
6.2 el和template區別
定義template屬性:
- 在前面的Vue實例中,我們定義了el屬性,用于和index.html中的#app進行綁定,讓Vue實例之后可以管理它其中的內容
- 這里,我們可以將div元素中的{{message}}內容刪掉,只保留一個基本的id為div的元素
- 但是如果我依然希望在其中顯示{{message}}的內容,應該怎么處理呢?
我們可以再定義一個template屬性,代碼如下:
重新打包,運行程序,顯示一樣的結果和HTML代碼結構:
那么,el和template模板的關系是什么呢?
- 在我們之前的學習中,我們知道el用于指定Vue要管理的DOM,可以幫助解析其中的指令、事件監聽等等。
- 而如果Vue實例中同時指定了template,那么template模板的內容會替換掉掛載的對應el的模板。
這樣做有什么好處呢?
這樣做之后我們就不需要在以后的開發中再次操作index.html,只需要在template中寫入對應的標簽即可
但是,書寫template模塊非常麻煩怎么辦呢?
- 沒有關系,稍后我們會將template模板中的內容進行抽離。
- 會分成三部分書寫:template、script、style,結構變得非常清晰。
6.3 Vue組件化開發引入
在學習組件化開發的時候,我說過以后的Vue開發過程中,我們都會采用組件化開發的思想。
那么,在當前項目中,如果我也想采用組件化的形式進行開發,應該怎么做呢?
查看下面的代碼:
當然,我們也可以將下面的代碼抽取到一個js文件中,并且導出。
6.4 .vue文件封裝處理
但是一個組件以一個js對象的形式進行組織和使用的時候是非常不方便的
- 一方面編寫template模塊非常的麻煩
- 另外一方面如果有樣式的話,我們寫在哪里比較合適呢?
現在,我們以一種全新的方式來組織一個vue的組件
但是,這個時候這個文件可以被正確的加載嗎?
- 必然不可以,這種特殊的文件以及特殊的格式,必須有人幫助我們處理。
- 誰來處理呢?vue-loader以及vue-template-compiler。
參考vue官網進行安裝配置
安裝vue-loader和vue-template-compiler
npm install vue-loader vue-template-compiler --save-dev
修改webpack.config.js的配置文件:
執行 npm run build 命令,又出現了報錯信息:
告訴我們要安裝一個插件,這是vue-router版本是15以上引起的
需要再額外添加如下配置:
執行 npm run build命令,運行成功:
七、plugin的使用
7.1 認識plugin
plugin是什么?
plugin是插件的意思,通常是用于對某個現有的架構進行擴展。
webpack中的插件,就是對webpack現有功能的各種擴展,比如打包優化,文件壓縮等等。
loader和plugin區別
- loader主要用于轉換某些類型的模塊,它是一個轉換器。
- plugin是插件,它是對webpack本身的擴展,是一個擴展器。
plugin的使用過程:
下面,我們就來看看可以通過哪些插件對現有的webpack打包過程進行擴容,讓我們的webpack變得更加好用。
7.2 BannerPlugin:為打包的文件添加版權聲明
我們先來使用一個最簡單的插件,為打包的文件添加版權聲明
該插件名字叫BannerPlugin,屬于webpack自帶的插件。
- 按照下面的方式來修改webpack.config.js的文件:
重新打包程序:查看bundle.js文件的頭部,看到如下信息
7.3 HtmlWebpackPlugin:打包html的plugin
目前,我們的index.html文件是存放在項目的根目錄下的。
我們知道,在真實發布項目時,發布的是dist文件夾中的內容,但是dist文件夾中如果沒有index.html文件,那么打包的js等文件也就沒有意義了。
所以,我們需要將index.html文件打包到dist文件夾中,這個時候就可以使用HtmlWebpackPlugin插件
HtmlWebpackPlugin插件可以為我們做這些事情:
- 自動生成一個index.html文件(可以指定模板來生成)
- 將打包的js文件,自動通過script標簽插入到body中
安裝HtmlWebpackPlugin插件
npm install html-webpack-plugin --save-dev使用插件,修改webpack.config.js文件中plugins部分的內容如下:
注意:
這里的template表示根據什么模板來生成index.html
另外,我們需要刪除之前在output中添加的publicPath屬性
否則插入的script標簽中的src可能會有問題
7.4 uglifyjs-webpack-plugin:js壓縮的Plugin
在項目發布之前,我們必然需要對js等文件進行壓縮處理 這里,我們就對打包的js文件進行壓縮
我們使用一個第三方的插件uglifyjs-webpack-plugin,并且版本號指定1.1.1,和CLI2保持一致
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev修改webpack.config.js文件,使用插件:
查看打包后的bunlde.js文件,是已經被壓縮過了。
八、搭建本地服務器
webpack提供了一個可選的本地開發服務器,這個本地服務器基于node.js搭建,內部使用express框架,可以實現我們想要的讓瀏覽器自動刷新顯示我們修改后的結果。
不過它是一個單獨的模塊,在webpack中使用之前需要先安裝它
npm install --save-dev webpack-dev-server@2.9.1devserver也是作為webpack中的一個選項,選項本身可以設置如下屬性:
- contentBase:為哪一個文件夾提供本地服務,默認是根文件夾,我們這里要填寫./dist
- port:端口號
- inline:頁面實時刷新
- historyApiFallback:在SPA頁面中,依賴HTML5的history模式
webpack.config.js文件配置修改如下:
執行node_modules\.bin\webpack-dev-server命令,啟動服務器
瀏覽器中輸入http://localhost:8080/打開index.html頁面:
或者在package.json文件中配置如下代碼:
執行npm run dev命令,啟動本地服務器:
我們可以再配置另外一個scripts:
--open參數表示直接打開瀏覽器
九、webpack配置的分離
原因:有些配置針對開發環境,有些配置針對生產環境,所以分開配置
package.json文件:
總結
以上是生活随笔為你收集整理的六、Webpack详解学习笔记——webpack的安装、起步、配置、loader的使用、webpack中配置Vue、plugin的使用、搭建本地服务器、webpack配置的分离的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三、操作系统——生产者-消费者问题(两个
- 下一篇: vue @input带参数_Vue 全家