project
- css
- bootstrap.min.css
- jb.css
- fonts
- 一些bootstrap的字體
- images
- 一些項目用到的圖片
- js
- bootstrap.min.js
- jquery.min.js
- jb.js
- index.html
- favicon.ico複製代碼
這個是公司要作的一個官方網站。因爲項目比較簡單,要求是單頁的,沒有頁面跳轉,因此只有一個 .html 文件。項目用了比較常規的 bootstrap + jquery 的開發,這個也沒啥好說的。考慮到 CDN 的可控性,因此把全部 bootstrap 的資源都下載到了本地進行引用。項目開始時是用了常規的 js 和 css 引用(css 放前面,js 放後面),在開發完成後,發現有時間多餘,就考慮用 webpack 對他進行處理一下,以鞏固和學習一下 webpack 所用到的知識css
npm init
先初始化一個 package.json 文件來管理咱們 webpack 所依賴的文件包。一路無腦回車便可。複製代碼
想要用 webpack ,那麼你首先確定要安裝 webpack 才能夠啊。用如下命令:
npm install webpack --save複製代碼
在根目錄下新建一個 webpack.config.js 文件,用來對 webpack 進行配置。
當有這個文件後,咱們系能夠在命令行中用如下命令來啓動配置好的 webpack 了。
webpack --config webpack.config.js複製代碼
以上雖然也能夠啓動配置好的 webpack。可是每次要輸這麼一串命令好像有點太長了(懶啊)。因此在 package.json 中修改這樣一項:
"script": {
+ "start": "webpack --config webpack.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
}複製代碼
這樣的話咱們就能夠在命令行中少敲幾個鍵盤了。直接用如下命令,就等同於上面的命令了:html
npm start複製代碼
好了,到這裏,初始化工做就作完了,那麼開始咱們的 webpack 配置吧node
webpack 建立應用程序全部依賴的關係圖(dependency graph)。圖的起點被稱之爲入口起點(entry point)。入口起點告訴 webpack 從哪裏開始,並根據依賴關係圖肯定須要打包的內容。能夠將應用程序的入口起點認爲是根上下文(contextual root) 或 app 第一個啓動文件jquery
跟其餘的 spa 應用不同,這樣的普通應用,其全部依賴都來自於 index.html 文件。若是說要有入口文件的話,怎麼也應該是 index.html 他自己吧。可是 webpack
基本都是用 .js 文件做爲入口文件,用 .html 做爲入口文件的...(反正我是沒有見到過)。至於這裏有啥緣由的話,你們就參考一下這篇文章吧。(其實我也不懂)webpack
因此說,無論怎麼樣,咱們都須要有個入口文件。git
那就無論怎麼樣,咱們常常看到的 webpack 的配置都是這樣的github
module.exports = {
entry: './index.js'
}複製代碼
那麼咱們無論三七二十一,先在根目錄下新建一個 index.js,而後讓他做爲咱們的入口文件。web
要知道,對於咱們原來的項目而言,咱們根本就是不須要這麼一個 index.js 文件的(沒有他,咱們能夠活得更好)。可是咱們又不得不建立了這樣一個文件。那麼問題來了,這麼建立出來的文件,裏面又該放什麼內容呢?咱們總不應救這麼建立一個空文件就算了吧。npm
在考慮這個問題的時候,咱們能夠先去看下 webpack 官方的那個很經典的圖(我很懶,就不放圖了,你們本身去網上找吧)。webpack 把左邊亂七八糟的 .js .css .png .jpg .sass。。。等等文件所有打包成了靜態資源。也就是說,webpack 打包的是除 html 外的全部資源,那麼咱們是否是隻要把這些資源都放到入口文件中那麼就可讓 webpack 幫咱們打包了呢?json
可是等等。其餘的都沒有問題,什麼 css 啊,什麼 js 啊,都好說,由於用來也不過這麼幾個,可是圖片呢,字體呢?我在項目中用了那麼多圖片,要所有再在 index.js 裏面再寫一遍!天吶!這是要命的啊!那麼我能不能偷懶下,就只寫 css 和 js 呢,其餘亂七八糟的我先無論?那就先這麼來吧。修改咱們的 index.js 文件,添加如下內容。
require('./css/bootstrap.min.css')
require('./css/jubang.css')
require('./js/jquery.min.js')
require('./js/bootstrap.min.js')
require('./js/jb.js')複製代碼
先這樣把他看成咱們的入口文件吧
出口文件就很好配置了,將他打包到根目錄下的 dist 目錄中。嗯 ~ 這很常見!
var path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}複製代碼
這個不知道怎麼配置,就先看這篇文章吧。
因此說,到這裏咱們的 webpack.config.js 就是這樣的:
var path = require('path');
module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style.loader',
'css-loader'
]
}, {
test: /\.(png|jpg|svg|git)$/,
use: [
'file-loader'
]
}, {
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}]
}
}複製代碼
這裏咱們用到了三個 loader,須要先安裝下
npm install css-loader style-loader file-loader --save複製代碼
這三個 loader 的做用你們仍是本身去網上查找吧
配置到這裏,咱們能夠先來打包一下,有問題再改嘛!
命令行切換到項目目錄下,執行如下命令:
npm start
打包結束後,項目的目錄結構
project
- css
- dist
- fonts
- images
- js
- node-modules
- favicon.ico
- index.html
- index.js
- package.json
- webpack.config.js
咱們能夠看到,項目根目錄下面多出來一個 dist 的目錄。沒錯,這個就是咱們 webpack 打包後文件生成的目錄,至於爲何會是 dist 目錄,那是由於你在 webpack.config.js 的 output 中設置的 path。
如今咱們來查看下 webpack 打包出了什麼東西
- dist
- xxxx.jpg
- xxxx.woff2
- xxxx.jpg
- xxxx.svg
- bundle.js
- xxxx.ttf
- xxxx.eot
- xxxx.woff複製代碼
注:xxxx表明一串數字和字母的組合,爲了表示方便就這麼寫了
打包文件中生成了一個 .js 文件,兩個 .jpg 文件,四個字體文件(.woff二、.ttf、.eot、.woff),和一個 .svg 文件
咱們來看下這是個類型的文件都來自哪裏吧複製代碼
bundle.js 是咱們根據咱們入口文件,將咱們在入口文件中全部的依賴資源都打包進去生成的。這個也是咱們最主要要關注的文件。
兩個 .jpg 文件是從哪裏來的呢?查看了兩張圖片以後,其實咱們會知道,這兩個圖片都是在咱們本身寫的 jb.css
中用來做爲 background-image
引入的。咱們說了,webpack 會根據入口文做爲起點,並根據依賴關係圖來進行打包的。換句話說,咱們在入口文件中依賴了 jb.css
,而 jb.css
依賴了兩張 .jpg 圖片,因此 webpack 根據依賴分析,將這兩張圖片也都一塊兒打包進來了。
四個字體文件的來源就須要咱們對 bootstrap 有必定了解了。若是熟悉 bootstrap 的同窗確定會知道,在 bootstrap 的依賴裏面,他正是依賴了這些字體,也就是說這些字體文件是從 bootstrap.min.css 文件中被打包進來的。其實我在作這個項目的時候,把 bootstrap 的源碼弄到本地的時候,會發現裏面有一個 fonts 的文件夾,也就是咱們項目根目錄下的 fonts 文件夾,這裏會有四個一樣文件結尾的字體文件和一個 .svg 結尾的 svg 文件。而這五個文件不就是咱們這裏多出來的五個文件嘛
若是還不放心的話,咱們能夠再作個驗證。修改 webpack.config.js 文件
{
test: /\.(png|jpg|svg|git)$/,
use: [
- 'file-loader'
+ 'file-loader?name=[hash:8].[name].[ext]'
]
}, {
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
- 'file-loader'
+ 'file-loader?name=[hash:8].[name].[ext]'
]
}複製代碼
咱們把圖片和字體文件,在 file-loader 處理後讓他的名字就變成 ’8位hash值-原文件名-後綴名‘的格式,那麼咱們就能夠比對這幾個文件的來源了。
從新打包後(你得先刪除原來的 dist 文件夾),咱們就能夠發現咱們的猜想是正確的!
雖然咱們的第一次打包成功了,可是仍是留下了幾個問題沒有解決:第一,個人 js、css、字體、圖片等資源都被打包進了 dist 目錄,可是做爲咱們的項目最主要的 index.html 文件呢?沒有這個文件,咱們打包出來的東西還有什麼意義呢!。第二,個人 images 文件夾裏有那麼多圖片,你這個 webpack 打包後爲何就只有兩張圖片了,其餘的呢?
那麼接下來讓咱們急需解決。
要解決第一個問題,咱們須要用到 html-webpack-plugin 插件。這個插件的具體說明能夠查看這裏。這個插件的做用是能夠將 html 文件打包,並自動添加對打包後的 output 文件的引用。具體如何使用,請先安裝:
npm install html-webpack-plugin --save複製代碼
修改配置文件:
var path = require('path');
+ var HtmlWebpackPlugin = require('html-webpack-plugin');
在 module 後面加
plugins: [
new HtmlWebpackPlugin({
template: './index.html'
})
]複製代碼
咱們在配置文件中引入了一個插件,並向 HtmlWebpackPlugin 構造函數傳遞了一個對象參數,在這個對象參數中,咱們指明瞭一個 template 字段,表面咱們要打包的 html 的文件源。而後咱們從新打包,再查看咱們的目錄就能夠發現 dist 目錄下多出了一個 index.html。因爲這個項目自己就是一個簡單的不依賴任何環境的項目,因此若是正常的話咱們直接打開 index.html 頁面就能在瀏覽器里正常顯示了。雖然不知道會怎麼樣,可是咱們仍是打開來試試吧。
當咱們打開 index.html 在瀏覽器中顯示的時候,咱們發現瀏覽器中好多圖片都不見了。細想咱們的項目代碼,發現除了在 jb.css 中的背景圖被正確顯示之外,其餘的定義在 img 標籤中的圖片沒有一張是顯示出來的。
因此雖然這個文件配置還有點問題沒解決,那麼咱們先來解決 html 中的 img 問題吧,也就是咱們上面提到的第二個問題。
要解決第二個問題(也就是 html 中的 img 問題),咱們須要用到 html-whithimg-loader,具體關於這個怎麼用能夠查看這裏。
修改配置文件,直接在 rules 中再添加一條配置規則
{
test: /\.(html|htm)$/,
use: [
'html-withimg-loader'
]
}複製代碼
這條配置規則代表,全部要處理的 html 文件首先會通過 html-withimg-loader 這個 loader 處理。就是這麼簡單能將咱們第二個問題解決嗎?試試看吧,事件是檢驗真理的惟一標準。
從新打包,再查看 dist 目錄,這一查看沒關係,發現 dist 目錄下多了好多圖片文件,密密麻麻,亂七八糟的,這些該不會就是咱們 html 中的圖片吧。按住本身的強迫症,先找到 index.html (咱們最關心的仍是他嘛),打開後再瀏覽器查看效果。發現果真,咱們的圖片都已經在了,並且樣式也差很少對了。可是這麼亂七八糟的 dist 目錄,怎麼會是咱們這種強迫症患者所想要的結果呢!咱們想要的是圖片都放在圖片文件夾下,字體都放在字體文件夾下,其餘的比較少的就先讓他在外面呆着吧。說幹就幹,咱們來調整一下咱們的配置文件
{
test: /\.(png|jpg|svg|git)$/,
use: [
- 'file-loader?name=[hash:8].[name].[ext]'
+ 'file-loader?name=images/[hash:8].[name].[ext]'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
- 'file-loader?name=[hash:8].[name].[ext]'
+ 'file-loader?name=fonts/[hash:8].[name].[ext]'
]
} 複製代碼
還有一個問題我已經忍了好久了,每次打包前,咱們都須要手動先去刪除上次打包留下來的 dist 目錄,這個就煩了,雖然只是一個 delete 的事情,可是作多了也煩啊!咱們想能不能讓 webpack 自動幫咱們作了這件事,讓咱們不須要手動去刪除。還好 webpack 夠智能,總能知足你提出來的各類無理取鬧。不過咱們先要裝一個插件:
npm install clean-webpack-plugin --save複製代碼
而後再配置文件中添加對這插件的引用
var HtmlWebpackPlugin = require('html-webpack-plugin');
+ var CleanWebpackPlugin = require('clean-webpack-plugin');複製代碼
在 plugins 中添加對這個插件的使用
new CleanWebpackPlugin(['dist'])複製代碼
這樣咱們就能不用手動刪除 dist 文件夾了。
從新打包下試試吧!
打包完後咱們在查看 dist 目錄就瞬間感受清爽多了有木有!
- dist
- fonts
- 一些字體文件
- images
- 一些圖片文件
- bundle.js
- index.html複製代碼
將打包後的項目再次在瀏覽器中查看,並查看控制檯會發現,控制檯報了一堆錯誤。其中有幾個是對一些 css、js 文件引用的錯誤。由於咱們把須要用的 css、js 都打包進了 bundle.js 中了。而咱們原來的項目是經過靜態資源引用的方式一個個導入 html 文件中的。因此,當咱們 webpack 打包成功後,就不須要對這些資源進行引用了,咱們只須要對 bundle.js(咱們打包後的文件)進行引用就能夠了,所幸的是,打包後的文件 webpack 已經自動幫咱們引用了。因此直接在原來項目中的 index.html 中幹掉那些 css、js 就能夠了。而後從新打包後就沒有這些資源找不到的亂七八糟的錯誤了。
可是,有一個小問題就是關於咱們的 .ico 文件。這是咱們網站的圖標文件。他的引用錯誤該如何解決呢?咱們能夠在生成 html 的時候,將這個問題先給解決了。修改配置文件
new HtmlWebpackPlugin({
template: './index.html',
+ favicon: path.resolve(__dirname, './favicon.ico')
})複製代碼
這樣的話咱們的圖標文件也就有了。
雖然一些亂七八糟的引用錯誤解決了,可是控制檯留下了一個讓咱們很是頭疼的問題:jquery 的引用問題:
Uncaught Error: Bootstrap's JavaScript requires jQuery複製代碼
這裏咱們須要用到 expose-loader 這個東西,關於他,能夠查看這裏,廢話很少說:
npm install expose-loader --save複製代碼
在 module 的 rules 中再添加一個 loader
{
test: require.resolve('./js/jquery.min.js'), // 引入 jquery
use: [{
loader: 'expose-loader',
options: '$'
}, {
loader: 'expose-loader',
options: 'jQuery'
}]
}複製代碼
固然,網上或許有其餘方法關於引入 jquery 的,這裏只是說一種。而後再打包咱們的頁面就沒有問題了:各類資源都有了,js 寫的效果也出現了。
雖然網站看上去沒啥問題了,可是細心的同窗確定會發現:當咱們打開網站的時候,他會先出現一個沒有樣式的頁面,而後一閃而逝,最後纔出現咱們預期的樣子。這是爲何呢?
緣由很好理解,由於咱們把 css 和 js 都打包進了同一個 bundle.js 裏面了。可是,這個 bundle.js 是在頁面最後面才加載進來的。也就是說,咱們的樣式被放在了頁面的底部被加載。這徹底不符合咱們的預期啊。咱們但願的是樣式在 head 中加載,而 js 腳本才放在頁面底部加載。因此咱們就不能把 css 和 js 一塊兒打包進 bundle.js 中了。
詳細資料看這裏
npm install extract-text-webpack-plugin --save複製代碼
增長 require
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');複製代碼
修改 css rules
{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract[{
fallback: 'style-loader',
use: 'css-loader'
}]
}複製代碼
增長 plugin
new ExtractTextWebpackPlugin('style.css')複製代碼
打包,而後咱們會發現 dist 中多了一個 style.css,而後再 index.html 的 head 中的多了對這個 css 的引用
增長 plugin
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})複製代碼
new HtmlWebpackPlugin({
template: './index.html',
favicon: path.resolve(__dirname, './favicon.ico'),
minify: {
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttribute: true,
collapseWhitespace: true
}
}),複製代碼
{
test: /\.(jpg|png|gif|svg)$/,
- use: 'file-loader?name=images/[hash:8].[name].[ext]'
+ use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
}複製代碼
暫時就先那麼多吧,沒時間寫了,之後再說。第一次發文,求輕虐。