自定义loader
-
Loader是用于对模块的源码进行转换处理的
-
loader本质上是一个导出为函数的JavaScript模块
-
loader runner库调用这个函数,然后将上一个laoder产生的结果或者资源文件传入进去;
-
所有的内容在经历过loader之后都必须转化为javascript字符串
-
content : 读取到的相关模块文件
Mate: 即一些 元素参数需要传入的
/* selfloader.js >> */ // 这个了loader被称之为normalloader module.exports = function (content, sourcemap, mate) { // TODO .. // 一般情况下只使用content } // 我们还可以拥有其他的loader module.exports.pitch = function (content, sourcemap, mate) { // TODO .. }
-
使用自定义loader
module.exports = { context: './xx', module: { rules: [ { test: /\.js$/, use: './selfloader' // 这里的路径是相对于 context的 } ] }, resolveLoader:{ modules: ["node_modules","./xxx/selfloader.js"] // 加上这个之后,我们可以再使用loader的时候不再 填上路径 } }
-
这里需要注意,我们在执行loader的过程中,默认是寻找的normalloader执行的,此时,是按照
rules
的从尾到首来执行的,但是,loader里面的其余loader则会按照rules
的从首到尾执行!!!在源代码中,
loader-runner
这个库是这样做的,它会先去执行代码中的pitch-loader,并且同时对loaderIndex++,执行完成之后,loader-runner
会根据loaderIndex再以此去取出normailloader,并且同时对loaderIndex– -
Enforce于loader执行顺序之间的关系
-
默认所有的laoder都是normail
-
在行内设置的loader是inline,(import ‘loader1!|loader2!./test.js’)
-
也可以设置enforce设置pre和post
-
rules: [ { test: /\.js$/, use: './selfloader', // 这里的路径是相对于 context的 enforce: "pre", // } ]
设置上了enforce属性之后,那么normail就会先执行
但是pitch会在最后执行
-
-
pitchloader阶段执行顺序
- post,inline,normail,pre
-
normal阶段执行顺序
- pre, normal, inline, post
-
异步loader
-
在前面的笔记中讲述的都是同步的loader
-
module.exports = function (context) { // 同步的loader中必须要有返回值才可以 // 有两种办法做到,第一是直接 return出去你的值, // 第二,调用laoder执行期上下文callback this.callback(err, context, sourcemap, mate); // 异步处理方式 const callback = this.async(); // this.async将会返回我们的callback,这是一个异步机制 setTimeout(() => { // 这里的第一个参数可以是err,也可以是context callback(context) }, 0) }
-
-
自定义loader参数的获取
-
我们需要借助官方提供的库
loader-utils
中的getOptions
-
const { getOptions } = require("loader-utils"); module.exports = function (content, sourcemap, mate) { getOptions(this) // 将会得到传入的参数 }
-
babel-loader
const { getOptions } = require("loader-utils"); const { babel } = require("@babel/core"); module.exports = function (content, sourcemap, mate) { const options = getOptions(this) // 将会得到传入的参数 const callback = this.async(); babel.tranform(content, options, ( err, result) => { callback(err, result.code) // result包含很多,比如ast树 }) }
-
-
loader解析markdown
-
marked
解析md文件,输出的是html格式的字符串 -
因为
loader-runner
的缘故,loader的返回值需要是一个js格式字符串,因此我们还需要借助html-loader
来解析html格式的字符串 -
这里推荐js库
highlight.js
帮助我们为marked解析出来为html做出美化const marked = require("marked"); const hljs = require("highlight.js") module.exports = function (content, sourcemap, mate) { // 执行完成之后我们会发现解析出来的代码会自动添加上一些class marked.setOptions({ highlinght: function(code, lang){ return hljs.highlight(lang, code).value } }) const html = marked(content); return content; } // 在src代码中我们可以自行去给class写一些样式 // 我们也可以使用 highlight.js 的默认样式处理我们的解析代码 import "highlight.js/styles/default.css" // 内部还有非常多的默认样式
-