loader
定义:文件加载器,用来对各种资源进行转换
特点
- loader的
执行顺序和代码书写的顺序是相反的:从右到左执行 - 第一个执行的loader会接收源文件做为参数,下一次执行的loader会接收前一个loader执行的返回值做为参数。
自定义loader
loader就是一个node模块,它输出了一个函数。当某种资源需要用这个loader转换时,这个函数就会被调用。并且,这个函数可以通过提供给它的this上下文访问loader API。
所以loader大概就是这样一个javascript文件:
module.exports = function(src){
// 可以通过this访问loader API
// this是由webpack提供的,可以直接使用
}
- 例如:写一个loader,功能是对txt文件的内容反转。有个test.txt文件,内容为abcdefg
/*
* 首先应该设置一个loaders文件夹
* 在loaders文件夹下写txt-loader文件夹
* txt-loader文件夹下写一个index.js文件,内容如下
*/
function txtLoader(source){
// source就是txt文件的内容(abcdefg),下面对内容进行处理
var result = source.split('').reverse().join('')
// 返回js源码,必修是string或buffer
return `module.exports = '${result}'`;
}
module.exports = txtLoader;
/*
* webpack.config.js文件中module下的rules对txt文件进行txt-loader 处理
*/
-
新建清除console语句的loader- 首先新建一个dropConsole.js文件
// source:表示当前要处理的内容
const reg = /(console.log()(.*)())/g
module.exports = function(source) {
// 通过正则表达式将当前处理内容中的console替换为空字符串
source = source.replace(reg,'')
// 在把处理好的内容return出去。输入输出都是字符串的原则,并可达到链式调用的目的供下一个loader处理
return source
}
- 在webpack的配置文件中引入
module:{
rules:[
{
test:/.js/,
use:[
{
loader:path.resolve(__dirname,'./dropConsole.js'),// loader的绝对路径
options:{
name:'前端'
}
}
]}
]}
plugin
定义
在webpack运行的声明周期中会广播许多事件,plugin可以监听这些事件,在特定的时刻调用webpack提供的API执行相应的操作。
作用
- clean-webpack-plugin 这个插件可以在每次打包输出前清空文件夹
- mini-css-extract-plugin 把css样式从js文件中提取到单独的css文件中
自定义plugin
plugin是一个具有apply方法的js对象。apply方法会被webpack的compiler(编译器)对象调用,并且compiler对象可在整个compilation(编译)生命周期内访问。
主要步骤;
- 编写一个JavaScript命名函数或者class(ES6语法)
- 在它的原型上定义一个apply方法
- 指定挂载的webpack事件钩子
- 处理webpack内部实例的特定数据
- 功能完成后调用webpack提供的回调
/*
* 首先在项目中定义一个plugins文件夹
*
*/
class MdToHtmlPlgin{
constructor(doneCallback, failCallback) {
// 存下在构造函数中传入的回调函数
this.doneCallback = doneCallback;
this.failCallback = failCallback;
}
apply(compiler) {
compiler.plugin('done', (stats) => {
// 在 done 事件中回调 doneCallback
this.doneCallback(stats);
});
compiler.plugin('failed', (err) => {
// 在 failed 事件中回调 failCallback
this.failCallback(err);
});
}
}
module.exports = MdToHtmlPlgin
/*
* apply方法会被webpack compiler调用,并且compiler对象可在整个编译生命周期访问
*
*/
打包文件清单.plugin
需求:每次webpack打包之后,自动产生一个打包文件清单,记录打包之后的文件夹dist里所有的文件的一些信息
class FileList {
static defaultoptions = {
outputFile:'assets.md'
};
constructor(options = {}){
// 可以接收自定义的options,如文件名等,进行合并
this.options = {...FileList.defaultOptions,...options}
}
apply(compiler){
// 在emit钩子里执行,是异步钩子
compiler.hooks.emit.tapAsync('FileList',(compilation,callback)=>{
const fileListName = this.options.outputFile
let len = Object.keys(compilation.assets).length
let content = `#一共有${len}个文件\n\n`
for(let filename in compilation.assets){
content += `- ${filename}\n`
}
compilation.assets[fileListName] = {
source:function(){
return content
}
size:function(){
return content.length
}
}
callback()
})
}
}
module.exports = FileList
区别
-
loader 用于加载某些资源文件。 因为webpack 本身只能打包commonjs规范的js文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。
-
plugin 用于扩展webpack的功能。它直接作用于 webpack,扩展了它的功能。当然loader也同时变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。
总结
loader 用于加载待打包的资源,plugin 用于扩展 webpack