本文是在windows系統(tǒng)下使用webpack阔蛉,其他系統(tǒng)只有命令行工具使用方式有區(qū)別,您可放心食用癞埠。
1 什么是webpack
webpack是一個前端開發(fā)打包工具状原。
它打包的是什么
通下面這張圖片可以看出,webpack可以將我們開發(fā)項(xiàng)目時編寫的多個不同類型的模塊依賴文件(其實(shí)就是我們寫的各個代碼文件)苗踪,打包成為幾個靜態(tài)資源文件(用來在瀏覽器上運(yùn)行)
為什么要使用webpack
如果你現(xiàn)在只是在簡單地學(xué)習(xí)html/css/js颠区,那么你就不會體會到webpack對你是否有用,如果你已經(jīng)具備了一些前端基礎(chǔ)通铲,準(zhǔn)備做一個完整項(xiàng)目練練手毕莱,那么使用webpack吧,他就像你的總管颅夺,幫你自動處理各種你本來需要親自動手的事情朋截,比如es6轉(zhuǎn)換為es5(現(xiàn)在大多瀏覽器對還不能es6很好的支持,所以要借用babel相關(guān)工具進(jìn)行轉(zhuǎn)換我們編寫的es6代碼)吧黄。
讓我們開啟webpack之旅吧
安裝webpack
推薦使用npm安裝webpack
npm是node.js的一個包管理工具部服,需要先安裝node.js才能使用(安裝教程請自行百度)。安裝完node.js后拗慨,新建一個文件夾project廓八,我們的項(xiàng)目就在該文件夾下面建立,project文件夾就是我們項(xiàng)目的根目錄胆描。
在項(xiàng)目根目錄新建模板文件index.html(模板文件是開始學(xué)前端的時候?qū)懙哪莻€html文件瘫想,只不過這里有更豐富的意義,這是后話昌讲,暫且不表)
在安裝webpack之前国夜,我們先在項(xiàng)目根目錄下面新建一個package.json文件配合webpack使用,這是一個npm安裝包的說明文件短绸。我們使用命令行工具cmd车吹,進(jìn)入我們的項(xiàng)目根目錄,自動創(chuàng)建package.json文件.
npm init
一路回車下去醋闭,知道最后輸入y確認(rèn)即可窄驹。
接下來我們安裝webpack,還是在項(xiàng)目根目錄下
npm install webpack -g 或者
npm install webpack --save 或者
npm install webpack --save-dev
-g 表示全局安裝
--save 和 --save-dev 表示安裝到你的項(xiàng)目根目錄证逻,--save 會把依賴包名稱添加到 package.json 文件的 dependencies 下乐埠,--save-dev 則添加到 package.json 文件的 devDependencies 下。dependencies是運(yùn)行時依賴,devDependencies是開發(fā)時的依賴丈咐。運(yùn)行時需要用到的包使用--save瑞眼,否則使用--save-dev,如果你還是不知道使用哪個棵逊,使用--save即可伤疙,以后安裝的包同理。
配置webpack
在package.json中對scripts對象進(jìn)行相關(guān)設(shè)置
"scripts": {
"start": "webpack" // 修改的是這里辆影,使用npm start 啟動打包命令徒像,直接用webpack命令也是一樣的
},
如果想要在運(yùn)行webpack的時候,使用一些webpack的參數(shù)蛙讥,可以在package.json 文件中配置
"scripts":{"webpack": "webpack --config webpack.config.js --progress看到打包過程 --display-modules看到打包了哪些模塊" --color彩色字體 --display-reason打看到包原因}
在項(xiàng)目根目錄下面創(chuàng)建webpack配置文件webpack.config.js
//基本結(jié)構(gòu)
module.exports = {
var path = require('path');
context: path.join(__dirname), //這是entry配置項(xiàng)的根目錄(絕對路徑)
entry: "./src/root.js",//打包入口文件锯蛀,就是打包誰
output: {
path: __dirname + "/dist/",//打包后文件放置的目錄路徑
// publicPath: "發(fā)布項(xiàng)目時在相對路徑前面添加的絕對路徑"
filename: "bundle.js"http://打包后文件的名字
}
}
context是運(yùn)行webpack打包程序時的上下文環(huán)境(項(xiàng)目根目錄),__dirname(注意是兩個下劃線)是node.js的一個全局環(huán)境變量。
entry:
寫法一:字符串 ----------打包一個入口文件次慢,如上
寫法二: 數(shù)組 ------------['./a.js', './b.js'] 打包兩個不相依賴的文件谬墙,打包在一起
寫法三:對象----------在多頁面應(yīng)用中,針對不同的頁面填寫不同的入口文件
entry: {
page1: './a.js',-----可以是一個
page2: ['./as.js', './b.js']-------可以是多個
}
此時如果還像上面那樣子寫output則只會生成一個輸出文件经备,且后面的打包文件會把前面輸出文件覆蓋,解決方法是在filename中添加一個占位符部默,區(qū)分不同輸出文件侵蒙,方法有三種:
1 [name] 就是entry對象的key值,page1, page2
output: {
filename: '[name]'.js,
path: __dirname + 'src'
}
2 [hash] 每次打包生成的一個hash值傅蹂,假設(shè)為“123asd”纷闺,可以和[name]一起使用
output: {
filename: '[name]-[hash]'.js,
path: __dirname + 'src'
}
多個打包生成文件hash相同,都是“123asd”
3 [chunkhash] 每一個chunk自己的hash值----打包時可以看到chunk(模塊),多個打包生成文件hash不同份蝴,可以和其他兩個結(jié)合使用犁功。
那么問題來了,因?yàn)槲覀兪褂昧薶ash值來編碼打包后生成的文件婚夫,而我們的html文件引用這個js文件時就必須保持同名浸卦,所以每次打包都需要手動更改引用文件的名字,相當(dāng)麻煩案糙。
我們可以使用一個插件來自動幫助我們引用打包后的js文件限嫌。
webpack插件 html-webpack-plugin
官網(wǎng):https://www.npmjs.com/package/html-webpack-plugin
先利用npm安裝
npm install html-webpack-plugin --save-dev
然后在webpack.config.js文件中引用
const htmlWebpackPlugin = require('html-webpack-plugin');
在 export.modules = {}中填寫
plugins: [
new htmlWebpackPlugin({----------初始化插件
template: 'index.html'-------模板文件(插件作用下生成文件的模板),注意這個路徑就是當(dāng)下目錄时捌,因?yàn)閣ebpack中有一個運(yùn)行上下文(context)怒医,即webpack的運(yùn)行所在目錄,而index.html在當(dāng)下目錄奢讨,所以路徑這樣寫沒問題
})
]
新生成的這個index.hml的所在目錄也是output的路徑下的目錄
output: {
filename: 'js/[name]'.js,
path: __dirname + '/dist/'
}
一個index.htm文件會生成在dist目錄下稚叹,里面有對[name]'.js的引用,[name]'.js會生成在./dist/js/目錄下
還可以增加另外一些參數(shù)
plugins: [
new htmlWebpackPlugin({
template: 'index.html',
filename: 'index-[hash].html', //也可以指定生成的文件的名字扒袖,
inject: 'head' //指定打包生成的js是在head標(biāo)簽中引用塞茅,不強(qiáng)制要求,用false
minify: {---------對項(xiàng)目進(jìn)行壓縮操作
removeComments: true,--------刪除注釋
collapseWhitespace: true----------刪除空格
}
})
]
此時我們根目錄下的index.html就不需要填寫打包出來的js的引用了
如果有多個頁面僚稿,同樣可以使用這個插件做到凡桥,只需要在plugins:[]數(shù)組中新增加一向即可,同時利用chunks:[ 'entry的key值' ]參數(shù)決定這個文件時要引入哪個入口文件的打包:
entry: {
main: './src/main.js',
a: './src/main.js',
b: './src/main.js',
c: './src/main.js'
}
plugins: [
new htmlWebpackPlugin({
template: 'index.html',
filename: 'a.html',
inject: 'body' ,
chunks: ['main', 'a']
})蚀同,
new htmlWebpackPlugin({
template: 'index.html'缅刽,
filename: 'b.html',
inject: 'body' ,
chunks: [ 'b'] 或者 excludeChunks: ['main', 'a', 'c']表示加載排除哪些chunk之外的chunk
}),
new htmlWebpackPlugin({
template: 'index.html'蠢络,
filename: 'c.html',
inject: 'body' ,
chunks: [ 'c']
})衰猛,
]
到現(xiàn)在webpack的基本配置也就完成了,當(dāng)然刹孔,如果你的項(xiàng)目沒有那么復(fù)雜啡省,只是用來練手,可以忽略htmlWebpackPlugin這個插件髓霞,一樣可以完美的使用webpack.
webpack應(yīng)用之loaders
你會發(fā)現(xiàn)卦睹,僅僅只有前面的工作,webpack好像并沒有多少卵用方库,反而增加了很多開發(fā)工作结序,想要解開這個困惑,請耐心看下去纵潦。
我們說過徐鹤,webpack是一個管家,既然如此邀层,我們就開始給它安排任務(wù)了返敬,正是這些任務(wù)的下放,才讓我們開發(fā)工作如釋重負(fù)寥院。
什么是loaders
先看官網(wǎng)的定義:
Loaders allow you to preprocess files as you require() or “l(fā)oad” them. Loaders are kind of like “tasks” in other build tools, and provide a powerful way to handle frontend build steps. Loaders can transform files from a different language like, CoffeeScript to JavaScript, or inline images as data URLs. Loaders even allow you to do things like require() css files right in your JavaScript!
大體意思就是劲赠,loaders能夠幫我們做一些預(yù)處理,將不同語言編寫的文件處理成能正常使用的樣子秸谢。
不同的loader具有不用的功能经磅,都需要先安裝,推薦使用npm安裝钮追。
我們先在這里將兩個重要的loader的使用预厌,以起到提綱挈領(lǐng)的作用,更多l(xiāng)oader使用將在以后更新元媚。
利用webpack構(gòu)建本地服務(wù)器
webpack-dev-server
在項(xiàng)目根目錄安裝轧叽,就是在cmd命令下利用cd命令苗沧,進(jìn)入我們創(chuàng)建的project文件夾
npm install --save-dev webpack-dev-server
配置
在webpack.config.js的module.exports = {}里面添加下面一項(xiàng)
devServer: {
contentBase: "./",//本地服務(wù)器所加載的頁面所在的目錄,即當(dāng)前project目錄
historyApiFallback: true,//不跳轉(zhuǎn)
inline: true//實(shí)時刷新
},
在package.json中配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server --inline --content-base --open"
},
實(shí)現(xiàn)修改代碼時炭晒,頁面時時更新待逞。
啟動本地服務(wù)器,默認(rèn)是8080端口网严,cmd進(jìn)入project文件夾下识樱,運(yùn)行以下命令
npm run server
注意: 進(jìn)入項(xiàng)目的根目錄運(yùn)行npm run server,webpack配置文件中本地服務(wù)器所加載的頁面所在的目contentBase的值應(yīng)該是從這里開始震束,比如要加載的文件在項(xiàng)目根目錄怜庸,那么contentBase: "./"
修改源代碼,頁面不能實(shí)時更新的問題
我們修改我們的源文件后垢村,自動打包生成的bundle.js其實(shí)只是一個虛擬的文件割疾,本地其實(shí)是沒有打包編譯的,所以我們不能使用本地路徑去引用嘉栓,在引用打包生成文件bundle.js的時候宏榕,將路徑改為絕對地址
src="http://localhost:8080/dist/bundle.js",即可
如果你還是沒有解決這個問題侵佃,打開你的webpack配置文件webpack.config.js麻昼,
將publicPath添加進(jìn)文件輸出
output: {
path: __dirname + "/dist/",
publicPath: "/dist/",
filename: "bundle.js"
},
如果問題還沒解決,看一下你的webstorm編輯器的設(shè)置馋辈,參考
https://www.cnblogs.com/wshiqtb/p/5924172.html
補(bǔ)充
npm run server表示運(yùn)行package.json中"scripts"中的server命令
package.json文件中output的路徑:
path----表示你打包后生成的打包文件放在你的電腦的那個目錄下
publicPath----表示服務(wù)器引用資源的路徑(相對于服務(wù)器根目錄)
webapck對圖片的處理
url-loader 或者 file-loader
npm安裝方法和前面一樣涌献,安裝哪一個可以看了下面的介紹自行決定
在模板文件和css文件中引用圖片寫相對地址,在react組件中引用圖片用相對地址找不到圖片首有,可以用絕對地址,從根目錄往下寫路徑枢劝,也可以用node的方法
<img src="${ require('相對路徑') }">
在webpack.config.js的module.exports = {}里面添加下面一項(xiàng)
{
test: /\.(png|jpg|gif|svg)$/i,
loader: 'file-loader',
query: {
name: 'assets/[name]-[hash:5].[ext]'//打包后的圖片放在assets文件夾下井联,圖片名字為 他的,名字+一個5位的hash值您旁,后綴名為ext
}
}
webpack2貌似不支持query烙常,可以直接用loader: 'url-loader?limit=8192&name=img/[name]-[hash].[ext]'這種寫法。
另一個處理圖片的loader
loader: 'url-loader?limit=8192'
當(dāng)文件大于limit值(bytes)的時候交給file-loader處理鹤盒,當(dāng)文件小于這個值時候蚕脏,圖片被轉(zhuǎn)換成一串base64的編碼,直接插入引用圖片的文件侦锯,使之變大驼鞭,但是卻不用通過http請求單獨(dú)去請求這張圖片資源
有一個loader可以用于壓縮圖片: image-webpack-------不要忘了先安裝
如果和url-loader寫在一起,可以這樣寫:
test: /.(png|jpg|gif|svg)$/i,
loaders: [
'url-loader?limit=8192&name=assets/[name]-[hash:5].[ext]',
'image-loader'
]----------注意loader中如果有多個參數(shù)時尺碰,處理順序是從右向左
上面就是兩個比較容易出錯的loader的使用挣棕,更多l(xiāng)oader的使用译隘,請參考“入門Webpack,看這篇就夠了http://www.reibang.com/p/42e11515c10f”