怎样写一个webpack loader
来源:互联网 发布:苹果桌面主题软件 编辑:程序博客网 时间:2024/05/22 16:52
在上一篇《webpack从入门到上线》介绍了wepack的配置和相关的概念,这一篇介绍怎样写一个webpack loader. 通过写一个js的html模板为例子。
上篇文章已提及,loader加载器就是对各种非正常资源的解析,转化成浏览器可以识别的js/css文件等,甚至可以说loader就是一个小型的编译器。例如sass loader:将sass格式编译成css,在安装sass的过程中你会发现,其实sass用的是C++,sass本身是面向对象的。但是本文不会介绍怎样写一个编译器(我也不知道),只是简单介绍下怎样写一个loader,抛砖引玉。
有什么样的场景需要写一个loader呢?
有一个就是在js里面写html的模板,会有点不太方便,一个是语法不是高亮的,第二个是需要双引号把每一行包起来,或者用数组push之类的,所以如果能够require一个html文件,然后转化成相应的js字符串,那就比较方便了。(如果你用react开发的,用jsx是比较自然的事情)。我在网上找了下,没有找到能够比较符合上面两点需求的loader,所以就自己尝试写一个吧。
js模板通常有三种场景:
- 纯html,一个文件就是一个模板,直接转成字符串即可;
- 需要有变量,一个文件有几个模板,每个模板对应一个变量
- 再复杂一点,模板是require了其它的工厂模块生成的字符串
现在开始来写loader
loader的基本框架
首先在工程的node_modules下面新建一个文件夹html-template-loader,在里面创建一个index.js做为这个loader的js文件。这样就可以在webpack.config.js里面添加一个loader了:
以.tpl.html作为后缀名,也就是说在逻辑代码里面引入一个.tpl.html结尾的文件,就归这个loader处理
重点就在于,这个loader怎么写呢?
loader也需要写成一个模块,一个基本的loader的写法:
是的,你没看错,一个loader就是这么简单。关键在于理解loader的机制——其实loader最后会创建一个模块,当我们require一个需要让loader的解析的文件之后,通过上面第7行的return——return里面的内容就是自动创建的模块的内容,跟平时自已写的模块的区别就在于这个要自己拼成一个js语法合法的字符串。
如上面生成的exports为:
那么webpack自动创建这样一个模块:
在我这个工程,这个模块的id为109,然后require的返回结果就是这个tpl的object。
另外一方面,初始化的时候可以拿到source,这个source就是webpack以utf-8读的整个文件的内容,以字符串的形式作为一个参数传进来。
所以现在目标就很明确了,我们需要处理这个source的字符串,然后再返回一个可以eval的字符串。需要定义loader的输入和输出的格式,这是作为loader开发者的权利,同时中间的处理过程对用户屏蔽。
loader的具体实现
把source这整一个文件,拆成一行一行处理:
难点就在于第8行的process函数怎么写,怎样拼成一个合法的tpl字符串。
如果是上面提到的第一种场景,则很简单,直接加就好了;
如果是第二种场景需要用变量区分的,那么需要自定义一个语法,由于我们用的是html,因为有高亮的功能。所以可考虑用html的注释的标签:
我们的语法就是<!–%变量名%–>,像上面定义了两个变量email和alert,接下来在process函数里面就可以进行识别、拼一个object的字符串。
如果是第三种场景需要引入第三方模块的,则需要在最后一行return的时候加上require这个函数的代码,即:
同样地,需要定义一个语法,require的代码用script的方式:
以一个generate的属性标志,这块是需要依赖的代码,也就是说要把它拼在前面。
正常的调用就用一个script,不带属性:
最后把它转成一个object.
经过合适的处理之后,最后生成的模块是这样的:
具体处理代码略,详见github
loader的高阶话题
1. loader支持链式,上一个loader的处理结果可以给下一个loader,像sass的loader是这样写的:
或者是写在配置文件里面:
sass处理完之后给css的loader,css的loader处理完后给style的loader,loader间的数据传递通过loader的定义的callback函数,例如上面的loader可以在return之前再加一行:
这样就可以传给下一个loader,最后一个loader一定要有return的内容;
2. loader可以缓存,可以加快速度
3. 其它:loader支持异步,loader的加载可以用异步的方式,loader可以传参数等等,详见官方文档:HOW TO WRITE A LOADER,官方文档比较绕,不是从0开始,也没有给一个完整的demo,具体可以再另外查查。
写loader关键在于怎么编译这个文件,上面是用的把它拆成一行一行的方式,然后做了个简单的处理,一般编译是要用到语法树。
- 怎样写一个webpack loader
- Webpack-源码四,从源码分析如何写一个loader
- towebp-loader诞生记~ 一个webpack 图片loader
- towebp-loader诞生记~ 一个webpack 图片loader
- WebPack Loader
- webpack loader
- webpack loader
- webpack loader
- vue-loader 与 webpack
- webpack loader 列表
- webpack loader加载器
- webpack loader一览
- webpack loader 一览表
- webpack之loader
- webpack之css-loader
- Webpack中的loader
- webpack中的babel-loader
- 【webpack】style-loader错误
- 贪心 -- 活动选择
- Effective前端1:能使用html/css解决的问题就不要使用JS
- redis学习笔记
- LeetCode 486 Predict the Winner 题解
- GDOI2017模拟 第三场(4.19~4.21)
- 怎样写一个webpack loader
- Linux中千M网卡与自适应的关系
- 分布式消息队列RocketMQ源码分析之3 -- Consumer负载均衡机制 -- Rebalance
- 从数据挖掘经典算法PageRank入门
- Webpack从入门到上线
- Linux C文件操作(三)
- 字符数组的定义和初始化
- Effective前端4:尽可能地使用伪元素
- JavaSE_JodaTime 应用 转换含英文简写的月份