loader
什么是loader
Loader的作用是幫助webpack去打包,webpack不能識(shí)別的文件冰悠。 webpack只能識(shí)別js文件,那些webpack不能識(shí)別的文件,就需要loader去進(jìn)行識(shí)別解析俯画。
下面以打包圖片為例,簡(jiǎn)單分析一下loader的工作過(guò)程司草。
首先下載一張圖片
-
將圖片存進(jìn)
src/imgs
之下艰垂,目錄結(jié)構(gòu)如下:- 項(xiàng)目結(jié)構(gòu)
- 在我們的入口文件引用,并將它插入進(jìn)html之中
?
import img from './imgs/twice.jpg'
console.log('file is', img)
const ImgElement = new Image();
ImgElement.src = img;
document.getElementById('root').append(ImgElement)</pre>
-
這時(shí)候直接去使用webpack打包會(huì)報(bào)錯(cuò)埋虹,因?yàn)閣ebpack不能識(shí)別以jpq為結(jié)尾的圖片文件猜憎。這時(shí)候需要借助loader
-
具體使用什么loader,翻閱官方文檔。圖片可以使用
file-loader
- 安裝:
npm install file-laoder -D
- 安裝:
將loader配置進(jìn)webpack的文件內(nèi)
-
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.jpg$/,//匹配jpg為結(jié)尾的文件
use: [{
loader: 'file-loader'
}]
}]
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, 'dist')
}
}
再運(yùn)行命令搔课,這次成功打包并且頁(yè)面上也可以看到胰柑。
- 結(jié)果
-
打開(kāi)控制臺(tái),可以看到剛剛輸出的內(nèi)容爬泥,是文件的文件名
- 控制臺(tái)
-
并且在dist目錄之下柬讨,也同樣生成了一份亂碼后的圖片,文件名與輸出內(nèi)容一致急灭。
由此可以看出姐浮,loader會(huì)先將文件移動(dòng)到dist這個(gè)文件夾下,然后再返回這個(gè)文件的地址葬馋,最終打包
-
總結(jié):file-loader執(zhí)行順序
會(huì)先將文件移動(dòng)到dist這個(gè)目錄下面
然后將這個(gè)文件的地址返回給這個(gè)變量
打包靜態(tài)資源
打包圖片
在上面的loader介紹中卖鲤,已經(jīng)使用過(guò)file-loader
對(duì)文件進(jìn)行過(guò)簡(jiǎn)單的打包肾扰。接下來(lái)會(huì)使用file-loader
以及url-loader
對(duì)圖片資源進(jìn)行打包
為loader配置option,對(duì)打包產(chǎn)生的文件增加更多的配置蛋逾。
使用
placehodler
設(shè)置文件名,當(dāng)前輸出文件是以hash值作為文件名使用
outputPath
設(shè)置圖片的存放路徑test: /\.jpg$/, use: [{ loader: 'url-loader', options: { name: '[name].[ext]', outputPath: 'images' } }] }]
重新生成的就是想要的文件路徑與文件名了集晚。
- image.png
使用url-loader
除了file-loader
以外,url-loader
也可以對(duì)文件資源進(jìn)行打包区匣。
安裝:npm install url-loader --save-dev
將原有的file-loader
替換成url-loader
module: {
rules: [{
test: /\.jpg$/,
use: [{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images'
}
}]
}]
}
圖片還是可以成功被打包出來(lái)偷拔。
那么url-loader
與file-loader
的區(qū)別在于哪里呢?我們可以點(diǎn)開(kāi)F12去查看一下這個(gè)文件
可以發(fā)現(xiàn)亏钩,這個(gè)文件已經(jīng)被url-loader
解析成了base 64的String莲绰。然后直接將這個(gè)字符串放進(jìn)bundle.js之中。
所以對(duì)比file-loader
, url-loader
更適用與小的圖片姑丑,并且可以少請(qǐng)求一次對(duì)圖片的http請(qǐng)求蛤签。不然圖片過(guò)大會(huì)增加頁(yè)面的加載速度,降低性能栅哀。
但url-loader
可以配置一個(gè)limit屬性震肮,在超過(guò)限制大小時(shí),會(huì)像file-loader一樣解析圖片留拾。
options: {
name: '[name].[ext]',
outputPath: 'images',
limit:8192 //limit to 8kb
}
這里將大小限制到8kb(源文件大小在11kb左右)戳晌,由于圖片大于限制大小,所以并不會(huì)被打進(jìn)bundle.js
打包樣式
想要給圖片增加一些樣式痴柔,添加一個(gè)style.css的樣式文件沦偎。里面添置一些文件的樣式:
.twice_img {
width: 400px;
height: 400px;
margin: auto;
}
將這個(gè)樣式文件引入到入口文件之中,并將這個(gè)class添加到img element之中竞帽。
import img from './imgs/twice.jpg'
import './style.css'
console.log('file is', img)
const ImgElement = new Image();
ImgElement.src = img;
ImgElement.classList.add('twice_img');
document.getElementById('root').append(ImgElement)
現(xiàn)在直接打包顯然肯定是會(huì)失敗的扛施。還是哪一個(gè)原則:webpack只能識(shí)別js,不能識(shí)別其他文件鸿捧。這里要引入兩個(gè)loader去識(shí)別css文件:css-loader
, style-loader
屹篓。
- 安裝
npm install style-loader css-loader -S
在安裝完成之后,在webpack.config.js文件之中添加css的配置
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
重新打包之后匙奴,打開(kāi)頁(yè)面,可以看到圖片變大堆巧,并且居中,樣式也覆蓋上去了泼菌。
這里說(shuō)明一下谍肤,為什么需要兩個(gè)loader。
- css-loader的作用是幫助webpack去識(shí)別樣式文件
-
style-loader的作用是將樣式掛載到html的style標(biāo)簽里哗伯。
從style里可以看到之前的樣式
打包scss文件
在項(xiàng)目中一啊不能都會(huì)使用sass
或者less
的預(yù)編譯css文件荒揣。這里也打包一下sass文件。
- 安裝loader
npm install sass-loader sass -S
改寫(xiě)一下樣式文件style.css
--->style.scss
body {
#root {
width: 100%;
height: 100%;
}
.twice_img {
display: block;
width: 400px;
height: 400px;
margin: auto;
}
}
更改一下打包策略
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
再重新打包一下焊刹,打開(kāi)頁(yè)面
添加postcss
如果在樣式中需要使用一些css新特性如grid
之類的系任,需要對(duì)樣式做兼容性處理恳蹲,前面拼上廠商前綴如,-webkit-
等
安裝postcss-loader
以及autoprefixer
npm install postcss-loader autoprefixer -S
配置postcss.config.js
,放在和webpack.config.js同一目錄之下俩滥。
module.exports = {
plugins: [
require('autoprefixer')
]
}
配置完之后重新打包嘉蕾,但是從頁(yè)面上并沒(méi)有看到拼的廠商前綴:
原因是在package.json文件之中需要添加瀏覽器支持配置,添加一下就可以看到了霜旧。
...
"devDependencies": {
"css-loader": "^3.5.3",
"style-loader": "^1.2.1"
},
"browserslist": [
"defaults",
"not ie <= 8",
"last 2 versions",
"> 1%",
"iOS >= 7",
"Android >= 4.0"
]
}
打包樣式错忱,loader常用的配置項(xiàng)
importLoaders
先描述一種場(chǎng)景,將scss的代碼進(jìn)行分割挂据,放置在不同的文件之中以清。然后在style.scss
這個(gè)文件中引入其他的scss文件。
這種場(chǎng)景之下崎逃,scss文件中引入的其他scss文件可能會(huì)不依次走
['style-loader', 'css-loader', 'sass-loader', 'postcss-loader']
這個(gè)順序玖媚,可能會(huì)直接走css-loader
以及style-loader
這兩個(gè)loader,從而導(dǎo)致樣式失效。
importLoaders
的作用就是婚脱,可以確保引入的scss文件也能將執(zhí)行css-loaders之前的loaders執(zhí)行完今魔。
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader
}
},
'sass-loader',
'postcss-loader'
]
modules
這loader使用的場(chǎng)景是:css模塊化。
比如我現(xiàn)在將創(chuàng)造圖片元素這一段邏輯抽離出來(lái)變成一個(gè)function障贸。并且放在一個(gè)新的文件createImg.js
之中错森。然后在index.js之中去調(diào)用這一個(gè)方法。
import img from './imgs/twice.jpg'
import './style.scss'
import createImage from './createImg'
createImage()
const ImgElement = new Image();
ImgElement.src = img;
ImgElement.classList.add('twice_img');
document.getElementById('root').append(ImgElement)
這樣從頁(yè)面上就會(huì)得到兩個(gè)一模一樣的圖片篮洁,并且樣式也一樣涩维。因?yàn)樵?code>index.js中都引用了樣式文件,在一定程度上造成了樣式污染袁波。為了讓兩個(gè)圖片擁有不一樣的樣式瓦阐,可以將樣式模塊化。
添加module的配置
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
// 0 => no loaders (default);
// 1 => postcss-loader;
// 2 => postcss-loader, sass-loader,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
}
同時(shí)對(duì)代碼進(jìn)行改寫(xiě)
import style from './style.scss'
import createImage from './createImg'
createImage()
const ImgElement = new Image();
ImgElement.src = img;
ImgElement.classList.add(style.twice_img); // twice_img是class的類名
document.getElementById('root').append(ImgElement)
分成不同模塊之后篷牌,生成的圖片樣式就不相同了睡蟋。
打包字體
在項(xiàng)目中最常見(jiàn)的字體應(yīng)用場(chǎng)景就是由font生成的那些icon了。
從iconFont上將字體下載之后枷颊,放在src/fonts
的文件里戳杀。附帶的字體申明樣式放在font.scss
之中,項(xiàng)目的目錄如下:
在生成的dom元素上加上相對(duì)應(yīng)的iconfont的class
const iconHtml = `<span class="icon iconfont icon-Dyanjing"></span><span class="icon iconfont icon-caidan"></span>`
document.getElementById('root').innerHTML = iconHtml;
最后更改一下打包規(guī)則,添加對(duì)字體文件的打包:
{
test: /\.(eot|woff2|woff|ttf|svg)$/,
use: [{
//placeholder
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts',
}
}]
}
打包一下夭苗,打開(kāi)頁(yè)面信卡,icon就成功出現(xiàn)啦: