内容简介:loader是导出为一个函数的node模块。该函数在loader转换资源的时候调用。给定的函数将调用loader API,并通过this上下文访问。pre => normal => inline => postloader执行首先会加载pitch-loader(书写loader的顺序),然后加载资源resource,最后执行normal-loader(正常加载loader的顺序) 如果pitch-loader有返回值,则会跳过后面的加载,直接走到上一层的normal-loader里面。
loader是导出为一个函数的node模块。该函数在loader转换资源的时候调用。给定的函数将调用loader API,并通过this上下文访问。
function loader(source){ return source } loader.pitch = function(){ console.log('pitch') } module.exports = loader 复制代码
加载自定义loader的几种方式
- 匹配单个loader(使用绝对路径)
{ test:/\.js$/, use:[ loader:path.resolve('path/loaderjs'), options ] } 复制代码
- alias
resolveLoader:{ alias:{ 'loader1':path.resolve('path/loader1') } }, module:{ rules:[ { test:/\.js$/, use:[ loader:loader1, options ] } ] } 复制代码
- 配置多个loader
resolveLoader:{ modules:[ path.resolve('node_modules'), path.resolve(__dirname, 'src', 'loaders') ] } 复制代码
loader的分类
- 在前面 pre
- 正常 normal
- 在后面 post
loader的顺序
pre => normal => inline => post
// index.js 加载顺序为 pre + normal + inline + post let str = require('inline-loader!./a.js') // index.js 加载顺序为 inline + post // -! 不会让文件 再去通过pre+normal loader 来处理了 // ! 没有normal // !! 什么都没有 只有自身 let str = require('-!inline-loader!./a.js') 复制代码
loader的组成
loader执行首先会加载pitch-loader(书写loader的顺序),然后加载资源resource,最后执行normal-loader(正常加载loader的顺序) 如果pitch-loader有返回值,则会跳过后面的加载,直接走到上一层的normal-loader里面。
- pitch-loader
- normal-loader
loader的特点
- 最后加载的loader必须返回一个js脚本
- 每一个loader都是一个模块
- 每一个loader都是无状态的,确保loader在不同模块转换之间不保存状态。
各种loader的实现
babel-loader
需要安装@babel/core、@babel/preset-env
let babel = require('@babel/core'); <!--loader 的 工具 库--> let loaderUtils = require('loader-utils') function loader(source){ <!--处理异步--> let cb = this.async(); <!--this loaderContext--> let options = loaderUtils.getOptions(this); <!--babel 转化源码--> babel.transform(source,{ ...options, sourceMap:true, filename:this.resourcePath.split('/').pop() // 文件名 },function(err,result){ cb(null,result.code,result.map) }) } module.exports = loader 复制代码
banner-loader
use:{ loader:'banner-loader', options:{ text:'xx', filename:path.resolve(__dirname,'banner.js') } } 复制代码
let loaderUtils = require('loader-utils') let fs = require('fs') <!--验证传递参数--> let validateOptions = require('schema-utils') function loader(source){ <!--添加缓存--> this.cacheable && this.cacheable() let options = loaderUtils.getOptions(this) let cb = this.async(); let schema = { type:'object', properties:{ text:{ type:'string' }, filename:{ type:'string' } } } validateOptions(schema,options,'banner-loader') if(options.filename){ <!--添加监听 当文件内容变化 自动打包--> this.addDependency(options.filename) fs.readFile(options.filename,'utf8',function(err,data){ cb(err,`/**${data}**/${source}`) }) }else{ cb(null,`/**${options.text}**/${source}`) } } module.exports = loader 复制代码
file-loader && url-loader
import p from './public.jpg' let img = document.createElement('img'); img.src = p; document.body.appendChild(img) 复制代码
file-loader
- 现将图片生成一个md5 发射到dist目录下
- 然后返回当前图片的路径
// file-loader let loaderUtils = require('loader-utils') function loader(source){ <!--生成md5文件--> let filename = loaderUtils.interpolateName(this,'[hash].[ext]',{content:source}) this.emitFile(filename,source) return `module.exports = "${filename}"` } // 将source 转化为二进制buffer loader.raw = true module.exports = loader // url-loader let loaderUtils = require('loader-utils') let mime = require('mime') function loader(source){ let {limit} = loaderUtils.getOptions(this); if(limit && limit > source.length){ return `module.exports = "data:${mime.getType(this.resourcePath)};base64,${source.toString('base64')}"` }else{ return require('./file-loader').call(this,source) } } loader.raw = true; module.exports = loader; 复制代码
less-loader && style-loader && css-loader
// less-loader let less = require('less') function loader(source){ let css; less.render(source,function(err,r){ css = r.css }) // 交给css-loader处理 return css; } module.exports = loader // style-loader function loader(source){ } loader.pitch = function(request){ // 这个request的就是当前路径 没有包含当前 // css-loader less-loader console.log(request); let script = ` let style = document.createElement('style'); <!--返回相对路径 只执行行内loader--> style.innerHTML = require(${loaderUtils.stringifyRequest(this, '!!' + request)}); document.head.appendChild(style); ` // 返回的结果 会在浏览器中运行 return script; } module.exports = loader // css-loader // css-loader的作用就是把所有url的内容 都变成require('文件名的形式') function loader(source) { let reg = /url\((.*?)\)/g; let current; let pos = 0; let arr = [`let lists = []`]; while (current = reg.exec(source)) { //lastIndex // 数组类型 [匹配的字符串,分组中的内容] let [matchUrl, p] = current; let index = reg.lastIndex - matchUrl.length // lastIndex就是匹配结束的位置 arr.push(`lists.push(${JSON.stringify(source.slice(pos, index))})`); arr.push(`lists.push("url("+require(${p})+")")`) pos = reg.lastIndex; } arr.push(`lists.push(${JSON.stringify(source.slice(pos))})`); arr.push(`module.exports = lists.join('')`); console.log(arr.join('\r\n')); return arr.join('\r\n'); } module.exports = loader; 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to Programming in Java
Robert Sedgewick、Kevin Wayne / Addison-Wesley / 2007-7-27 / USD 89.00
By emphasizing the application of computer programming not only in success stories in the software industry but also in familiar scenarios in physical and biological science, engineering, and appli......一起来看看 《Introduction to Programming in Java》 这本书的介绍吧!