webpack-loader是怎样炼成的

 

啰嗦两句

 

学习这件事从学习动机上来看,可以分成两种情况:主动学习和被动学习。主动学习就是,某天你浏览网页的时候,看到一个酷到没朋友的效果,赶紧打开开发者工具,看看用了什么 css 属性,用了什么库或者框架实现的,这是主动学习。

还有一种是被动学习。就拿我来说,之前用 mpvue 写小程序的时候,页面的 json 配置都是写在 main.js 里面的,loader 会从 main.js 解析出对应的代码块,然后为我生成对应的配置文件。但是前两天,当我又初始化一个新项目的时候(使用的是 mpvue-loader1.1.4),这个好用的特性居然消失了,我需要在目录下自己手动建一个 json 文件写页面配置。

人有这么一种本性,从不好的体验切换到好的体验很快,但是再切回去就很难受😢。所以,这回只有硬着头皮写个 webpack loader 来回归原来的体验了。实现的功能很简单,就是重新实现 mpvue 原有的功能,从 js 文件中解析出配置项的内容,并生成一个json文件到对应的文件夹中。

loader 是干什么的

 

无图言卵,先上个图:
1539876855690.jpg

把 webpack 想像成一个工厂,loader 就是一个个身怀绝技的流水线工人,有的会处理 svg,有的会压缩 css 或者图片,有的会处理 less,有的会将 es6 转换为 es5。他们在 webpack 的调度下 (确切的说是 loader-runer),井井有条的完成自己工作后,把自己处理的结果交给下一个工人,直到最后由 webpack 将他们的劳动成果生成 dist 目录下的文件。

所以一个 loader 用一个函数来表示,应该是这样的:

module.exports = function(content, map, meta) {   return content; }; 

上面我们就定义了一个什么都不干还拿工资的 loader,它就是拿到内容后原样交给下一个 loader 同学。但是,它现在其实还只是一个函数 -- 因为它还没有混入 webpack loader 内部啊,现在我们帮他打入 webpack 的 loader 内部:

// webpack.config.js  ... module: {   rules: [     {       test: /\.js$/,       include: [resolve('src'), resolve('test')],       use: [         {           loader: path.resolve('path/to/my-loader.js'), // 本 loader😊           options: {a: 1}         },         ... 其他 loader       ]     }   ] } 

作为一个什么都不做的 loader,它在 rules 下面使用 /\.js$/ 这个正则表达式,告 (hu) 诉 (you) webpack 它可以处理 js 文件, 还通过 includes 字段,说明了它的业务范围只负责 src 和 test 目录下的 js 文件。

现在回到上面的图,大部分 loader 还是实实在在办事的。有的可以处理文本文件,如 css 预处理,进去的是 less 语法的文件,出来的是 css 语法的文件;有的可以处理二进制文件,比如将较小的图片变成 base64 字符串。还有的 loader 买一送二,比如 mpvue-loader, 输入的是 vue 文件,但是会输出 wxss,wxml,js 三个文件。但是,这些工作仅靠 loader 自己是办不到的,它需要和 webpack 沟通。也就是说,干活是需要工具的,这个工具就是 loader 的上下文 (context)。

loader 的工具箱 --context

 

根据 官方文档 的解释,loader context 表示在 loader 内使用 this 可以访问的一些方法或属性。还是在上面的那个啥都不干 loader 上说明:

const path = require('path') module.exports = function(content){   console.log('resource', this.resource) // 文件路径带 query   console.log('query', this.query)// 对应配置中的 options {a: 1}   console.log('resourcePath', this.resourcePath)// 文件路径   this.emitFile('main.json', JSON.stringify({hello: 'world'}))// dist目录下生成一个 json 文件   this.emitWarning('这个 loader 啥都不干')// 会触发一个警告⚠️   // this.emitError('这个 loader 啥都不干')// 会导致本次编译过程失败   return content } 

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信