寫在前面
這篇文章是自己在整理webpack相關的東西時候突發奇想,想整理出一套由淺入深的博文以此鞭策自己學習,也希望能夠幫助想學習webpack的同學,目前都是入門級別的,大佬請出門右轉。
學習完本篇文章,我希望您能夠掌握以下幾點:
- webpack是什麼
- webpack有什麼有點
- webpack.config.js配置項中,出口(entry)、入口(output)、外掛(plugins)的基本作用和配置方法。
- html-webpack-plugin、 clean-webpack-plugin 外掛的作用和使用方法。
統一說明,本文中所用到的npm包管理工具均採用淘寶映象(cnpm),原因你懂得。
webpack版本基於3.0版本,本文中具體是3.8.1版本。
什麼是webpack
webpack是一個用以對現代Javascript應用程式模組打包工具,它和gulp、grunt的不同之處在於webpack提供了一整套前端模組化開發的解決法案;webpack把資源作為模組來處理,這裡的資源不止於javascript,還包括html、css、圖片、字型等等。
webpack的優點
- 程式碼分割(code splitting),在開發過程中,webpack允許我們將程式碼按照不同職能分割成不同模組進行開發,並且在載入中可以按需載入,減少載入時間。
- 外掛化,webpack提供了豐富的外掛介面,通過配置不同的外掛,可以實現我們想要的效果,非常靈活。
- 裝載機制,webpack中,我們可以通過提供的loaders預處理專案檔案,包括js、css、html、image等。
- 高效能,webpack使用非同步I/O流載入模組,並具有多個快取級別,在漸進式編譯中,速度表現很棒。
- 開發方便,weback提供sourceMap和sourceUrl,方便開發者定位除錯,並且通過中介軟體可以實現專案的熱更新,這個在開發中很有作用。
webpack使用
構建專案結構
1、初始化, 新建一個資料夾,取名叫webpackDemo,通過控制檯或者git bash定位到當前檔案下面,執行命令:
npm init //淘寶映象用 cnpm init複製程式碼
然後一路enter,初始化後,會在該資料夾下面生成一個package.json檔案,然後,再次在命令列內執行:
npm install //淘寶映象用 cnpm install複製程式碼
2、專案結構搭建, 在webpackDemo資料夾下:
- 新建src目錄,用於存放開發相關的資原始檔;
- 在src目錄下新建js、css、views等不同型別的資料夾,以此存放相對應的開發檔案。
- 新建dist目錄,用於存放打包後生成的檔案;
- 和src目錄下一樣,新建js、css、views等資料夾,存放打包後的檔案(案例中,先新建一個js資料夾,因為我們現在只用js來體驗webpack)。
- 新建index.html檔案。
- 新建webpack.config.js,這是webpack預設關於打包相關的配置檔案。
新建.babelrc檔案,放置babel相關配置,和webpack.config.js一樣,babel的配置檔名稱,也是固定的,即:.babelrc
注意: webpack預設會讀取webpack.config.js 中的相關配置,如果更換其他名字,webpack預設是找不到配置資訊的。(當然我們也可以去指定webpack讀取的配置檔案,在現階段,我們暫不考慮);
最終的專案結構如下:
初體驗
1、程式碼編寫,開啟根目錄下的index.html,引入webpack最後編譯的的js檔案,我麼定義js名稱叫做bundle.js。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack demo</title>
</head>
<body>
<!-- 我們給最終編譯出的js叫做bundle.js-->
<script src="./dist/js/bundle.js"></script>
</body>
</html>複製程式碼
2、在src/js資料夾下面,新建app.js,作為webpack編譯的入口檔案,並新增一個方法,在控制檯列印出hello world
// app.js
function Hello() {
console.log('hello world')
}
Hello()複製程式碼
3、接下來,我們開啟webpack.config.js,給webapck編譯指定規則:
// webpack.config.js
var path = require('path');
module.exports = {
entry: path.resolve(__dirname, './src/js/app.js'),//指定webpack打包的入口是app.js
output: {
path: path.resolve(__dirname, './dist/js'),//指定打包後js檔案放置的位置
filename: 'bundle.js'//指定打包後的js名稱,這個就是index.html最終引入的js的名稱
}
}複製程式碼
1、配置路徑用path.resolve()處理,是為了確保路徑是從根目錄開始絕對定位到指定位置,webpack3.0要求我們在配置路徑相關的時候使用絕對路徑;
2、path模組是nodejs內建的處理路徑相關的模組。
現在讓我們開啟命令列,執行webpack編譯
//如果還未安裝webpack,則先執行安裝
cnpm i webpack --save-dev
// 安裝完成後執行編譯
webpack複製程式碼
編譯執行完成後,控制檯輸出以下則表示執行成功。
此時檢視dist/js目錄,會發現新增了一個bundle.js的檔案,在瀏覽器中開啟index.html,再開啟控制檯,成功輸出hello world。
看到這裡,估計有人要打人了,就這玩意有啥用,浪費我青春!我要輸出的hello world要你這麼麻煩幹啥。額!騷年,先放下你手上的磚頭,有話好好說。
大名鼎鼎的webpack當然不止這就完了,接下來,讓我們一步一步真正開始認識webpack。
webpack配置---生成帶hash值的js檔案
現在,我們來看一下webpack配置檔案中的output選項的相關配置,細心的你也許發現,我們最終生成的的bundle.js是我們設定好的,每次打包後生成的名字是不會改變的,但是在實際專案中,為了確保程式碼更改前後無衝突以及版本回退等一系列問題,每次打包後的包檔案,我們會給他打上一個獨一無二的標記,用以區分版本,這又是怎麼實現的呢?
實際上,webpack在打包編譯的時候,會把不同模組的程式碼分別指定一個chunkhash值,最後整體打包後的js會生成一個hash值 (需要注意chunkhash和hash是不一樣的),我們只需要在output配置項中給filename屬性一個填寫hash的佔位符,這樣在每次編譯的時候,就會生成帶有hash值得js檔案:
var path = require('path')
module.exports = {
entry: path.resolve(__dirname, './src/js/app.js'),
output: {
path: path.resolve(__dirname, './dist/js'),
filename: 'bundle-[hash].js'//[hash]為編譯時填寫hash的佔位符,也可以填寫chunkhash等
}
}複製程式碼
再次執行編譯,我們會發現,新生成的檔案已經帶有hash值了:
webpack配置---根據模板動態生成Html
上面我們已經動態生成了帶有不同hash值得js了,那麼問題又來了,既然每次生成的js檔案都不一樣,我們如何去載入生成的js呢,要知道,在index.html裡面,我們寫的是bundle.js啊!
為了解決這個問題,我們就想,如果每次webpack打包編譯後自動將生成的js注入到我們的index.html模板中,這樣我們就不用在我們的index.html中手動新增bundle.js了,不就解決了這個問題麼。
實際上!這種思想正是webpack為我們提供的解決方案-- html-webpack-plugin。
首先,我們通過命令列安裝這個外掛
cnpm install html-webpack-plugin --save-dev複製程式碼
然後,我們在配置檔案裡新增對html-webpack-plugin的相關配置
var path = require('path');
//引入html-webpack-plugin模組
var htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, './src/js/app.js'),
output: {
path: path.resolve(__dirname, './dist/js'),
filename: 'bundle-[hash].js'
},
//初始化外掛
plugins:[
new htmlWebpackPlugin({
template:'index.html',//定義外掛讀取的模板檔案是根目錄下的index.html
filename:'index.html'//定義通過模板檔案新生成的頁面名稱
})
]
}複製程式碼
在配置檔案中,我們新增了plugins這個配置屬性,並初始化html-webpack-plugin外掛,現在我們去index.html中刪除js的引用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack demo</title>
</head>
<body>
<!-- <script src="./dist/js/bundle.js"></script>-->
</body>
</html>複製程式碼
再次執行webpack命令,編譯成功後!再看看我們的dist目錄下,果然生成了index.html。
提醒一
html-webpack-plugin外掛執行的時候,需要在專案安裝webpack,如果是全域性安裝的webpack,在此處執行會報錯:Cannot find module 'webpack/lib/node/NodeTemplatePlugin'。
。
解決辦法就是在本地安裝webpack,定位到專案的根目錄下執行以下命令即可。
cnpm install webpack複製程式碼
提醒二
細心的你可能又發現,生成的index.html也在dist/js資料夾下面,這和我們想要的結果不一樣,因為我們想要在dist資料夾下把html、js以及後面的css都分開來,為了解決這個問題,我們須將配置檔案的output選項更改一下:
var path = require('path')
var htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, './src/js/app.js'),
output: {
// path: path.resolve(__dirname, './dist/js'),
path: path.resolve(__dirname, './dist'),//將輸出的路徑定位到dist一級就好,然後再filename配置項中,指定二級目錄。
//filename: 'bundle-[hash].js'
filename: 'js/bundle-[hash].js'
},
plugins: [
new htmlWebpackPlugin({
template: 'index.html',
filename:'index.html'
})
]
}複製程式碼
在配置中,我們將output中的path路徑指定到dist一級就好,至於生成的js路徑,我們就將js放置在filename選項下,配置完成後,我們再次在命令列執行"webpack"命令,最終發現,dist目錄下新生成了index.html頁面,而js,則依然在js資料夾下生成。
webpack配置---清除dist資料夾下面的重複檔案
到目前為止,我們的案例可以動態的生成帶有自己hash命名的js檔案,但是我們發現檔案在一直增加,新生成編譯檔案之前並沒有刪除上一次編譯的檔案,這會讓專案原來越大。為了解決這個問題,我們需要再次引入一個外掛---clean-webpack-plugin。
老規矩,首先是安裝,在命令列執行:
cnpm install clean-webpack-plugin --save-dev複製程式碼
然後在配置檔案中引入外掛並例項化
var path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin');
//引入外掛模組
var cleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: path.resolve(__dirname, './src/js/app.js'),
output: {
path: path.resolve(__dirname, './dist'),
filename: 'js/bundle-[hash].js'
},
plugins: [
new htmlWebpackPlugin({
template: 'index.html'
}),
//初始化外掛配置項
new cleanWebpackPlugin(
['dist'], //匹配要刪除的檔案,這裡則指定每次對dist資料夾進行清理
{
root: __dirname,//指定外掛根目錄位置
verbose: true, //開啟在控制檯輸出資訊
dry: false //啟用刪除檔案
}
)
]
}複製程式碼
在配置中,我們將引入的clean-webpack-plugin例項化,並設定了要刪除檔案的目錄和一些顯示設定,再次在命令列執行"webpack"命令,發現之前的檔案被刪除了,只剩下最新生成的相關檔案。
;寫在最後
這一節,我們向大家初步介紹了webpack的使用,並且從頭開始搭建了一個webpack執行的編譯環境,初次體驗了一下webpack,當然,webpack的功能遠遠不止於此,它的最重要的功能loader我們還沒開始,目前筆者所展示的這些,只是webpack很小很小的一部分。
再次提醒讀者盆友,讀完本篇文章您應該瞭解以下內容:
- webpack是什麼
- webpack有什麼有點
- webpack.config.js配置項中,出口(entry)、入口(output)、外掛(plugins)的作用和基本配置方法。
- html-webpack-plugin、 clean-webpack-plugin 外掛的作用和使用方法。
下一節,我們將在此基礎上學習webpack的載入器用法,包括babel編譯es6、css預處理、autoprefixer用法、css與js檔案分割等,歡迎大家提出寶貴意見,一起學習。
這是前端最好的時代,也是前端最壞的時代,前端不止,學習不停,願各位讀者努力向前,早日成為前端高手。