loader
主要是用於把模塊原內容按照需求轉換成新內容,以便用來加載非 JS 模塊!
通過使用不同的loader
,Webpack
可以把不同的文件都轉成JS文件,比如CSS、ES6/7、JSX等。
讓我們來看看這些必須要掌握的loader!
1.loader的編寫
1.1 loader的使用
- test:匹配處理文件的擴展名的正則表達式
- use:loader名稱,就是你要使用模塊的名稱
- include/exclude:手動指定必須處理的文件夾或屏蔽不需要處理的文件夾
- options:爲loaders提供額外的設置選項
默認loader
的執行順序是從下到上、*從右向左,當然執行順序也可以手動定義,接下來我們依次介紹常見的loader
,來感受loader
的魅力!
我們基於這個基礎配置來繼續編寫:
const path = require("path");
const dev = require("./webpack.dev");
const prod = require("./webpack.prod");
const merge = require("webpack-merge");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const base = {
entry:'./src/index.js',
output: {
filename: "[name].js",
path: path.resolve(__dirname, "../dist")
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, "../public/template.html"),
hash: true,
minify: {
removeAttributeQuotes: true
}
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [path.resolve('xxxx/*'),'**/*'],
}),
]
};
module.exports = env => {
if (env.development) {
return merge(base, dev);
} else {
return merge(base, prod);
}
};
2.處理CSS文件
2.1 解析css樣式
我們在js
文件中引入css樣式!
import './index.css';
再次執行打包時,會提示css無法解析
ERROR in ./src/index.css 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
這個時候需要安裝loader
npm install style-loader css-loader --save-dev
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
}
2.2 抽離樣式文件
默認只在打包時進行樣式抽離
module.exports = env => {
let isDev = env.development;
const base = {/*source...*/}
if (isDev) {
return merge(base, dev);
} else {
return merge(base, prod);
}
};
安裝抽離插件
npm install mini-css-extract-plugin --save-dev
配置抽離插件
{
test: /\.css$/,
use: [
!isDev && MiniCssExtractPlugin.loader,
isDev && 'style-loader',
"css-loader"
].filter(Boolean)
}
!isDev && new MiniCssExtractPlugin({
filename: "css/[name].css"
})
最終文件配置貼一下:
const path = require("path");
const dev = require("./webpack.dev");
const prod = require("./webpack.prod");
const merge = require("webpack-merge");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = env => {
let isDev = env.development;
const base = {
entry: "./src/index.js",
output: {
filename: "[name].js",
path: path.resolve(__dirname, "../dist")
},
module: {
rules: [
{
test: /\.css$/,
use: [
!isDev && MiniCssExtractPlugin.loader,
isDev && 'style-loader',
"css-loader"
].filter(Boolean)
}
]
},
plugins:[
!isDev && new MiniCssExtractPlugin({
filename: "css/[name].css"
}),
new HtmlWebpackPlugin({
filename: "index.html",
template: path.resolve(__dirname, "../public/template.html"),
hash: true,
minify: {
removeAttributeQuotes: true
}
}),
].filter(Boolean)
};
if (isDev) {
return merge(base, dev);
} else {
return merge(base, prod);
}
};
2.3 css預處理器
不同的css預處理器
要安裝不同的loader來進行解析
- sass: sass-loader node-sass
- less: less-loader less
- stylus: stylus-loader stylus
使用sass
{
test:/\.scss$/,
use:[
!isDev && MiniCssExtractPlugin.loader,
isDev && 'style-loader',
"css-loader",
"sass-loader"
].filter(Boolean)
}
在css文件中可能會使用@import
語法引用css
文件,被引用的css
文件中可能還會導入scss
{
test: /\.css$/,
use: [
!isDev && MiniCssExtractPlugin.loader,
isDev && 'style-loader',
{
loader:"css-loader",
options:{
importLoaders:1 // 引入的文件需要調用sass-loader來處理
}
},
"sass-loader"
].filter(Boolean)
},
2.4 處理樣式前綴
使用postcss-loader
增加樣式前綴
npm install postcss-loader autoprefixer
在處理css前先增加前綴
{
test: /\.css$/,
use: [
!isDev && MiniCssExtractPlugin.loader,
isDev && 'style-loader',
{
loader:"postcss-loader",
options:{
plugins:[require('autoprefixer')]
}
},
"postcss-loader",
"sass-loader"
].filter(Boolean)
},
或者也可以創建postcss
的配置文件postcss.config.js
module.exports = {
plugins:[
require('autoprefixer')
]
}
可以配置瀏覽器的兼容性範圍 .browserslistrc
cover 99.5%
2.5 css壓縮
在生產環境下我們需要壓縮css
文件,配置minimizer
選項,安裝壓縮插件
npm i optimize-css-assets-webpack-plugin terser-webpack-plugin --save-dev
在webpack.prod.js
文件中配置壓縮
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
optimization:{
minimizer:[new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]
}
2.6 文件指紋
- Hash:整個項目的hash值
- chunkhash:根據入口產生hash值
- contentHash:根據每個文件的內容產生的hash值
我們可以合理的使用hash
戳,進行文件的緩存
!isDev && new MiniCssExtractPlugin({
filename: "css/[name].[contentHash].css"
})
3.處理文件類型
3.1 處理引用的圖片
import logo from './webpack.png';
let img = document.createElement('img');
img.src = logo;
document.body.appendChild(img);
使用file-loader
,會將圖片進行打包,並將打包後的路徑返回
{
test:/\.jpe?g|png|gif/,
use:{
loader:'file-loader',
options:{
name:`img/[name].[ext]`
}
}
}
3.2 處理icon
二進制文件也是使用file-loader
來打包
{
test:/woff|ttf|eot|svg|otf/,
use:{
loader:'file-loader'
}
}
3.3 轉化成base64
使用url-loader
將滿足條件的圖片轉化成base64,不滿足條件的url-loader
會自動調用file-loader
來進行處理
{
test:/\.jpe?g|png|gif/,
use:{
loader:'url-loader',
options:{
limit:100*1024,
name:`img/[name].[ext]`
}
}
}
4.小結
通過對loader的使用,我們瞭解到loader可以把其他類型模塊都處理成JS模塊,以便加載使用。這其實就是webpack中非常重要的混淆依賴中的一部分。
下一篇文章我們將一起來探討如何解析處理JS模塊,希望大家繼續關注和支持!