自己搞webpack還是從1.X開始的,從一開始都一直想寫歌簡單的教程神馬的贰您,但是遲遲沒有動筆。今天決定了功茴,開始記錄,所以先從概念開始寫孽亲,咱還是先要了解webpack是個什么鬼,是做什么的玲昧,以及為什么要使用它篮绿,它與其他工具比如說Grunt和gulp有什么區(qū)別亲配,好吧犬钢,帶著這幾個問題開始正題玷犹。來個華麗麗的分割線
- 什么是webpack歹颓,有什么作用
[官方解釋]:webpack 是一個現(xiàn)代 JavaScript 應(yīng)用程序的模塊打包器(module bundler)。當(dāng) webpack 處理應(yīng)用程序時肺魁,它會遞歸地構(gòu)建一個依賴關(guān)系圖(dependency graph)鹅经,其中包含應(yīng)用程序需要的每個模塊瘾晃,然后將所有這些模塊打包成少量的 bundle - 通常只有一個劫拢,由瀏覽器加載偶洋。
[自己的理解]:你就可以把它但工作一個模塊打包工具玄窝。它可以打包js帽氓、css黎休、html壮啊、image等文件玄渗。 - 為什么要使用webpack
今的很多網(wǎng)頁其實(shí)可以看做是功能豐富的應(yīng)用藤树,它們擁有著復(fù)雜的JavaScript代碼和一大堆依賴包。為了簡化開發(fā)的復(fù)雜度微王,前端社區(qū)涌現(xiàn)出了很多好的實(shí)踐方法:
a:模塊化钧大,讓我們可以把復(fù)雜的程序細(xì)化為小的文件;
b:類似于TypeScript這種在JavaScript基礎(chǔ)上拓展的開發(fā)語言:使我們能夠?qū)崿F(xiàn)目前版本的JavaScript不能直接使用的特性眶诈,并且之后還能能裝換為JavaScript文件使瀏覽器可以識別;
c:scss,less等CSS預(yù)處理器
.........
這些改進(jìn)確實(shí)大大的提高了我們的開發(fā)效率,但是利用它們開發(fā)的文件往往需要進(jìn)行額外的處理才能讓瀏覽器識別,而手動處理又是非常反鎖的,這就為WebPack類的工具的出現(xiàn)提供了需求萄金。
3.它與Grunt和gulp的區(qū)別
好多人都說學(xué)了這幾款工具之后,發(fā)現(xiàn)他們做的事情基本上都是一樣的孙乖,比如說整合好幾個js文件(模塊)成一個文件蜗帜,然后進(jìn)行壓縮和檢查語法蔬顾,又比如說調(diào)用loader把ES6轉(zhuǎn)換成ES5(通用瀏覽器可識別的語法),css的預(yù)編譯等。
你可以這樣子理解
Grunt :一種自動化任務(wù)處理工具。
gulp:基于流的自動化構(gòu)建工具
從功能上說展氓,它們都是為了實(shí)現(xiàn)模塊化開發(fā)的一種手段簿废。
從工作方式上說歪赢,webpack屬于模塊化管理工具埋凯,其他兩個屬于任務(wù)管理工具换怖,或許這樣說不是很準(zhǔn)確条摸,借用其他朋友說的一句話解釋一下吧,Grunt和是一種自動化任務(wù)處理工具,而webpack是一種模塊化管理方案线梗,目測,webpack應(yīng)該是一個趨勢偏陪,功能很強(qiáng)大,配置簡單。不過你要想一步一步來配置你環(huán)境,用gulp就很適合笋颤,如果你想一下子就配備大部分需要的環(huán)境,那么webpack就可以秉版,蘿卜青菜各有所愛祭犯,好像偏題了粥惧,這里說的是他們的區(qū)別。
webpack的四個核心概念:入口(entry)、輸出(output)督函、loader、插件(plugins)。
1. 入口(entry)
string | [string] | object { <key>: string | [string] } | (function: () => string | [string] | object { <key>: string | [string] })
起點(diǎn)或是應(yīng)用程序的起點(diǎn)入口。從這個起點(diǎn)開始,應(yīng)用程序啟動執(zhí)行。如果傳遞一個數(shù)組,那么數(shù)組的每一項(xiàng)都會執(zhí)行璧南。
動態(tài)加載的模塊不是入口起點(diǎn)篓像。
簡單規(guī)則:每個 HTML 頁面都有一個入口起點(diǎn)盒粮。單頁應(yīng)用(SPA):一個入口起點(diǎn),多頁應(yīng)用(MPA):多個入口起點(diǎn)。
//單入口配置,多用于SPA
module.exports = {
entry: './path/to/my/entry/file.js'
};
//單入口配置嘿架,多用于MPA
entry: {
home: "./home.js",
about: "./about.js",
contact: "./contact.js"
}
//動態(tài)入口配置
entry: () => new Promise((resolve) => resolve(['./demo', './demo2']))
p:如果傳入一個字符串或字符串?dāng)?shù)組佃乘,chunk 會被命名為 main
扎唾。如果傳入一個對象,則每個鍵(key)會是 chunk 的名稱,該值描述了 chunk 的入口起點(diǎn)庵楷。
2. 輸出(Output)
配置 output
選項(xiàng)可以控制 webpack 如何向硬盤寫入編譯文件.可以存在多個入口文件對應(yīng)一個出口文件的配置。
配置output
屬性的最低要求是差凹,將它的值設(shè)置為一個對象,包括以下兩點(diǎn):
-
filename
用于輸出文件的文件名。 - 目標(biāo)輸出目錄
path
的絕對路徑小渊。
//單入口-出口 - 多應(yīng)用于SPA
const config = {
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
};
module.exports = config;
//多入口-出口 -多應(yīng)用于MPA
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
3. Loader
{1:概念}
loader 用于對模塊的源代碼進(jìn)行轉(zhuǎn)換吗垮。loader 可以使你在 import
或"加載"模塊時預(yù)處理文件蔚舀。因此礼患,loader 類似于其他構(gòu)建工具中“任務(wù)(task)”,并提供了處理前端構(gòu)建步驟的強(qiáng)大方法领曼。可以利用ts-loader將 TypeScript 轉(zhuǎn)為 JavaScript,可以利用babel-loader將ES6語法轉(zhuǎn)換成ES5語法,style-loader的目的是為了在html中以style的方式嵌入css,css-loader是為了在js里邊通過require引入css,等等一系列的任務(wù)都可以通過loader實(shí)現(xiàn)摆屯。
//安裝相應(yīng)loader
npm install --save-dev css-loader
npm install --save-dev ts-loader
//實(shí)現(xiàn)loader配置
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' }
]
}
};
{2:使用 Loader}
有三種使用 loader 的方式:
-
配置[Configuration](推薦):在 webpack.config.js 文件中指定 loader廷没。
module: { rules: [ { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } } ] } ] }
-
內(nèi)聯(lián):在每個
import
語句中顯式指定 loader狭归。import Styles from 'style-loader!css-loader?modules!./styles.css';
-
CLI:在 shell 命令中指定它們潭流。
//對 .jade 文件使用 jade-loader //對 .css 文件使用 style-loader 和 css-loader。 webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
p:盡可能使用 module.rules
钳幅,因?yàn)檫@樣可以減少源碼中的代碼量,并且可以在出錯時牡属,更快地調(diào)試和定位 loader 中的問題。
{3:特性}
-
loader 支持鏈?zhǔn)絺鬟f废士。一組鏈?zhǔn)降?loader 將按照先后順序進(jìn)行編譯氢架。loader 鏈中的第一個 loader 返回值給下一個 loader警检。在最后一個 loader,返回 webpack 所預(yù)期的 JavaScript。
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
loader 可以是同步的,也可以是異步的使碾。
loader 運(yùn)行在 Node.js 中,并且能夠執(zhí)行任何可能的操作。
-
loader 接收查詢參數(shù)隔躲。用于對 loader 傳遞配置宣旱。
{ test: /\.(eot|woff|svg|ttf|woff2|gif|appcache)(\?|$)/, exclude: /^node_modules$/, loader: 'file-loader?name=[name].[ext]' }, { test: /\.(png|jpg)$/, exclude: /^node_modules$/, loader: 'url?limit=20000&name=[name].[ext]' //后面的limit的參數(shù)浑吟,當(dāng)你圖片大小小于這個限制的時候组力,會自動啟用base64編碼圖片 }
-
loader 也能夠使用
options
對象進(jìn)行配置燎字。//一般常使用.babelrc文件進(jìn)行配置。 { "presets": [], "plugins": [] // 插件 }
除了使用
package.json
常見的main
屬性脱柱,還可以將普通的 npm 模塊導(dǎo)出為 loader榨为,做法是在package.json
里定義一個loader
字段随闺。-
插件(plugin)可以為 loader 帶來更多特性矩乐。
//1 //HtmlwebpackPlugin //為html文件中引入的外部資源如script分歇、link動態(tài)添加每次compile后的hash职抡,防止引用緩存的外部文件問題 new HtmlwebpackPlugin({ template: path.resolve(__dirname, 'src/index.html'), inject: 'body' }) //2 //CommonsChunkPlugin //提取代碼中的公共模塊缚甩,然后將公共模塊打包到一個獨(dú)立的文件中擅威,以便在其他的入口和模塊中使用郊丛。 new CommonsChunkPlugin({ name: 'vendors', filename: 'vendors.js', minChunks: function(module) { return isExternal(module); } }) //3 //webpack.ProvidePlugin //定義標(biāo)識符宾袜,當(dāng)遇到指定標(biāo)識符的時候,自動加載模塊绅络。像我們常用的jQuery new webpack.ProvidePlugin({ jQuery: 'jquery', $: 'jquery' }) //4 //ExtractTextPlugin //將樣式從js中抽出恩急,生成單獨(dú)的.css樣式文件 new ExtractTextPlugin('style.css', { allChunks: true // 提取所有的chunk(默認(rèn)只提取initial chunk衷恭,而上面CommonsChunkPlugin已經(jīng)把部分抽離了) })
loader 能夠產(chǎn)生額外的任意文件灭袁。
4. 插件(Plugins)
{1:概念}
插件是 wepback 的支柱功能茸歧。插件目的在于解決 loader 無法實(shí)現(xiàn)的其他事软瞎。
{2:使用 Plugins}
-
配置涤浇。
常用的一些插件在前邊loader里邊都有介紹只锭,這里就不更多介紹了
module: { rules: [ { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } } ] } ] }
-
Node API
const webpack = require('webpack'); //訪問 webpack 運(yùn)行時(runtime) const configuration = require('./webpack.config.js'); let compiler = webpack(configuration); compiler.apply(new webpack.ProgressPlugin()); compiler.run(function(err, stats) { // ... });