1. 常见的loader
1.1 file-loader(处理静态资源模块)
原理是把打包过程中识别出的资源模块,移动到输出目录,并且返回新的地址名称。
使用场景:当我们需要的模块,仅仅是从源代码移动到打包目录,则可以使用file-loader来处理,比如txt, svg, csv, excel和图片资源等
安装
npm i file-loader -D
webpack配置
module:{
rules:[
{
test:/\.(png|jpe?g|gif)$/,
//use使⽤⼀个loader可以⽤对象,字符串,两个loader需要⽤数组
use:{
loader:' file-loader',
// options额外的配置,⽐如资源名称
options:{
name:'[name]_[hash].[ext]', // 占位符 [name]⽼资源模块的名称 [ext]⽼资源模块的后缀
outputPath:'images/' //打包后的存放位置
}
}
}
]
}
index.js
import pic from "./logo.png";
var img = new Image();
img.src = pic;
img.classList.add("logo");
var root = document.getElementById("root");
root.append(img);
1.2 url-loader (file-loader加强版)
url-loader内部使用了file-loader,所以可以处理file-loader所有的事情,但是遇到图片模块,则会把图片转为base64格式字符串,并打包到js里。这种方式适合小体积的图片。
安装
npm i url-loader -D
配置
module:{
rules:[
{
test:/\.(png|jpe?g|gif)$/,
use:{
loader:'url-loader',
options:{
name: '[name]_[hash].[ext]',
outputPath:'images/',
//⼩于2048,才转换成base64
limit:2048
}
}
}
]
}
1.3 样式处理
css-loader
处理css模块之间的关系,并合成一个css
style-loader
会把css-loader生成的内容,以style标签挂载到页面的head部分
安装
npm i css-loader style-loader -D
配置
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
}
less样式处理
less
把less语法转成css
less-loader
less和webpack沟通的桥梁
安装
npm i less less-loader -D
配置
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
}
样式自动添加前缀
需要用到postcss-loader
和autoprefixer
安装
npm i postcss-loader autoprefixer -D
配置
// webpack.config.js
{
test:/\.css$/,
use:['style-loader','css-loader','postcss-loader']
}
// postcss.config.js
module.expors = {
plugins:[
require('autoprefixer')({
overrideBrowserslist:['last 2 version', '>1%']
})
]
}
2.如何编写自定义loader
loader 本质就是一个函数,声明式函数,不能用箭头函数
原理是拿到源代码,经过处理后,返回处理后的源码即可。
接下来我们来实现一个简单的loader
- 创建一个替换源码字符串的loader
//index.js
console.log("hello aaa");
// loader/replaceLoader.js'
module.exports = function(source){
console.log(source, this, this.query)
return source.replace('aaa', 'bbb')
}
// 需要⽤声明式函数,因为要上到上下⽂的this,⽤到this的数据,该函数接受⼀个参数,是源码
- 在配置中使用loader
const path = require('path')
module:{
rules:[
test:/\.js$/,
use:path.resolve(__dirname, './loader/replaceLoader.js')
]
}
- 如何给loader配置参数,loader如何获取参数
在loader中获取参数有两种方式,this.query
和loader-util
(需要安装)
// webpack.config.js
{
test:/\.js$/,
use:{
loader:'path.resolve(__dirname, './loader/replaceLoader.js'),
options:{
name:'bbb'
}
}
}
// loader/replaceLoader.js
const loaderUtils = require("loader-utils");//官⽅推荐处理loader,query的⼯具
module.exports = function(source){
//this.query 通过this.query来接受配置⽂件传递进来的参数
// return source.replace('aaa', this.query.name)
const options = loaderUtils.getOptions(this)
const result = source.replace('aaa', options.name)
return result
}
- 如何返回多个信息,不止是处理好的源码呢, (this.callback)
// loader/replaceLoader.js
const loaderUtils = require("loader-utils");//官⽅推荐处理loader,query的⼯具
module.exports = function(source){
//this.query 通过this.query来接受配置⽂件传递进来的参数
// return source.replace('aaa', this.query.name)
const options = loaderUtils.getOptions(this)
const result = source.replace('aaa', options.name)
this.callback(null, result)
}
//this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
- 如何处理异步 (this.async)
const loaderUtils = require("loader-utils");
module.exports = function(source){
const options = loaderUtils.getOptions(this)
// 定义⼀个异步处理,告诉webpack,这个loader⾥有异步事件,在⾥⾯调⽤下这个异步
// 使⽤this.asycn来处理,他会返回this.callback
const callback = this.async()
setTimeout(()=>{
const result = source.replace('aaa', options.name)
callback(null, result)
},1000)
}
- 处理loader的路径问题
// webpack.config.js
{
resolveLoader:{
modules:['node_modules', './loader']
},
module:{
rules:[
{
test:/\.js$/,
use: 'replaceLoader'
}
]
}
}