webpack學習筆記1:基本概念
前言:
現在在日常的開發中,webpack已經是必不可少的東西了,現在的需求基本都是用webpack對資源進行打包整合,所以打算寫一點關于webpack的東西,這是第一篇,主要是介紹一些基本的概念。
webpack的概念
眾所周知,webpack是一個模塊打包器,他會把項目里的各種資源進行統一打包,webpack打包的時候會遞歸的構建一個依賴圖,每個用到的模塊都在這個流程圖上,最后輸出一個javascript文件。
webpack由四個核心部分構成,分別是:
entry(入口)
output(出口)
loader(加載器)
plugin(插件)
entry入口
前邊說過,webpack打包的時候會構建一個依賴圖,而entry就是這個圖的起點,webpack會知道,從哪個文件開始進行他的打包之旅。
webpack中有多種方法指定entry
簡單語法
用法:
const config = {entry:'./path/app.js'
};module.exports = config;
其實這是下邊方式的簡寫
const config = {entry:{main:'./path/app.js'}
};module.exports = config;
上邊表示app.js文件是這個項目的入口文件,entry的值除了是一個字符串,還可能是一個數組。
如果你的項目很小,沒有依賴其他的大型庫,那么這種簡單的寫法是個很好的選擇,從app.js開始,按照依賴圖一次打包各個文件。
缺點是,這種配置缺乏一定的靈活性。
對象語法
前邊說,簡單寫法缺乏靈活性,是因為,加入依賴了一個很大的庫,比如react,每次執行打包的時候都需要把react打包一遍。
const config = {entry:{app:'./path/app.js',vendor:'./vendor.js'}
}module.exports = config;
上面看起來項目有兩個入口,app和vendor,兩者獨立于彼此,分別開始構建各自依賴的資源。這種方式常見于只有一個入口(app而不是vendor)的單頁面(SPA)應用。
vendor是一些公共的庫,不會發生輕易改變,甚至是不會改變,把他們提取出來會優化打包的效率,可以理解起到了一個緩存的作用。
多頁面應用程序
const config = {entry:{page1:'./src/page1/page1.js',page2:'./src/page2/page2.js',page3:'./src/page3/page3.js'}
}module.exports = config;
當項目是一個多頁面應用的時候,需要的是多個webpack入口,所以就會有多個依賴圖。這個我們看到,page1頁面的入口是page1.js,其他兩個頁面的也是如此。
多頁面不能用一個單個的入口的原因是,每次載入一個新的html,需要重新下載新的文件,所以頁面需要哪個文件,就依賴哪個。
我們可以用CommonshunkPlugin來每個頁面的共享代碼創建bundle,提供復用的機制,提高效率。
output出口
有入口就有出口,在webpack中,output表示項目的出口,即打完包輸出的文件。
即便有多個entry入口文件,可是在webpack中,只有指定一個輸出配置
用法
const config = {entry:'./sec/app.js',output:{filename:'bundle.js',path:'./src'}
}
配置項是一個對象,對象里有兩個屬性。
filename:表示打包輸出之后的文件名
path:表示打包輸出的路徑
多個入口的情況下
如何項目是有多個入口的情況下,這個時候使用占位符來確保每個文件有唯一的名稱
const config = {entry:{app1:'./src/app1.js',app2:'./src/app2.js'},output:{filename:[name].js,path:__dirname+'/dist'}
}
在dist文件夾下,會有打完包之后的app1.js和app2.js兩個文件。
loader加載
loader提供方法進行構建,包括去源代碼進行轉換,把不同的語言轉成javascript,或者把圖片轉成dataUrl或者把sass文件中換成css。總之,loader是webpack的精髓,功能強大。
示例
比如,我們要用webpack加載css文件或者把typescript轉成js,首先要安裝對應的loader。
npm install css-loader --save-dev
npm install ts-loader --save-dev
然后指示每個css使用css-loader,每個ts使用ts-loader.
const config = {entry:'./src/app.js',output:{filename:'bundle.js',path:__dirname+ '/dist'},module:{rules:[{test:/\.css$/,use:'css-loader'},{test:/\.ts$/,use:'ts-loader'}]}
}
使用loader的三種方式
在webpack中,有三種使用loader的方法,
配置,在webpack的配置文件中配置(推薦)
內聯,在import中指定相關loader
CLI, shell命令使用(這個先不研究了)
配置
module.rules允許你在webpack中配置多個loader,這是最好的方式,可以讓你一目了然的看到項目到底配置了哪些loader。
module:{rules:[{test:/\.css$/,use:[{loader:'style-loader'},{loader:'css-loader',options:{modules:true}}]},]
}
這是webpack2的語法。
內聯
可以在import或者任何等價于import的語句中使用loader,不過用的很少,其語法是這樣的
import style from 'style-loader!css-loader?modules'
盡量使用上一種配置的方法,因為可以減少代碼量,每次都import引用也是一件很麻煩的事情。
loader解析
多數情況下,loader將會從模塊路徑開始解析,就是npm install安裝的模塊。
loader需要導出為一個函數,通常采用node兼容的js寫法,有的時候也可以將自定義loader作為應用程序中的文件。通常情況下,采用xxx-loader的方式命名。
plugin插件
插件是webpack的支柱功能,一句話概括插件的作用就是做loader不能做的事情。
剖析
插件是一個擁有apply屬性的js對象。apply會被webpack compiler調用,comliler是個對象,可以再在整個編譯周期訪問。
function plugin1(){...
}
plugin.prototype.apply = function(compiler){compiler.plugin('run',function(compiler,callback){console.log('webpack構建開始了');callback();})
}
用法
由于插件是可能存在選項或者是參數的,所以在webpack文件中,需要在plugin屬性里用new把需要的插件傳進去,看下邊例子
配置
const config = {entry:{app:'./src/app.js',vendor:'./src/vendor.js'},output:{filename:[name].js,path:__dirname+'/dist'},nodule:{loaders:[{test:/\.css$/,use:'style-loader!css-loader' }]},plugin:[new webpack.optimize.UglifyJsPlugin(),new HtmlWebpackPlugin({emplate:'./src/index.html'})]
};module.export = config;
后記
這篇文章主要介紹了一下webpack的基礎概念,包括webpack配置文件的四個主要部分,entry,output,loader,plugin的寫法。