<%=require("@tpl/container.tpl")({rightbox:require('./index.tpl')()})%>
在这个模板中我想获取container.tpl,并向其注入rightbox变量,此变量是index.tpl的模板,container模板内容如下
<%= require('./header.tpl')() %>
<%= require('./leftnav.tpl')() %>
<%= rightbox %>
<%= require('./footer.tpl')() %>
然后container中获取header,左侧导航栏,footer的模板文件,rightbox存放模板字符串的变量注入其中,让其拼接成完整页面,html-loader是没有此功能的,于是我想起自己做一个loader,把html-loader和ejs-loader相互结合,制作成自己想要的既能转码base64,又能向其中注入变量。
可能有人说了,webpack中loader可以有依赖表达式,可以在中间加个感叹号表示依赖。
这种方法放在style样式文件是可以的,放在js,或ts是可以的,唯独放在模板文件是不可以的。
为什么呢,我们先简单的看一下html-loader和ejs-loader输出接口的源码:
html-loader
var exportsString = "module.exports = ";
if (config.exportAsDefault) {
exportsString = "exports.default = ";
} else if (config.exportAsEs6Default) {
exportsString = "export default ";
}
return exportsString + content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
if(!data[match]) return match;
var urlToRequest;if (config.interpolate === 'require') {urlToRequest = data[match];} else {urlToRequest = loaderUtils.urlToRequest(data[match], root);}return '" + require(' + JSON.stringify(urlToRequest) + ') + "';}) + ";";
var lodash=require("lodash");
ejs-loader
var template = _.template(source, _.extend({}, query, options));
return 'module.exports = ' + template;
由此可见,这些loader返回给你的都是一个以module.exports=为开头的字符串,html-loader中module.exports等于的是一个真正的html片段,而ejs-loader则是写了一个函数function(x){var str='a'+x+'b';return str;},你写的那些特殊字符全部被转换成字符串中加变量拼接的方式了,require进来的是一个函数,因此还要再给他执行以下,当然也可向其注入变量获取不同的字符串,
html-loader在编译这些字符串已经将字符串编译成没有空格和换行的形式了,如果同时加载了两次loader,那么第二次加载的loader拿到的字符串便是第一次以module.exports开头的已经编译过的字符串,那么结果只会报错。
于是乎,我做了一个自己的jcy-loader,说是自己做的,其实也就是改写了一下html-loader,说到这里,可能有人会说了,你这是抄袭,盗版,但我要说的是,虽然这个loader是基于html-loader改写的,但是他却又html-loader没有的功能,如果能够站在巨人的肩膀上,为什么还要自己去堆一座山呢。我们程序员的工作不是日复一日的创作,因为你的创作很可能是别人已经做过的,我们应该多思考,模仿它并超越它。
首先引用了ejs-loader加载的lodash插件
var lodash=require("lodash");
然后注释掉这段代码,这样就不会对输入进来的字符串进行编译了。然后就可以放进下一个loader进行编译。
// if(config.interpolate && config.interpolate !== 'require') {
// // Double escape quotes so that they are not unescaped completely in the template string
// content = content.replace(/\\"/g, "\\\\\"");
// content = content.replace(/\\'/g, "\\\\\'");
// content = compile('`' + content + '`').code;
// } else {
// content = JSON.stringify(content);
// }
在html-loader中替换图片资源为为+require()+的字符转的地方加上这句话,然后return出来
var d=content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
if(!data[match]) return match;
var urlToRequest;
if (config.interpolate === 'require') {
urlToRequest = data[match];
} else {
urlToRequest = loaderUtils.urlToRequest(data[match], root);
}
return "'+require("+JSON.stringify(urlToRequest)+")+'";
}) + ";";
return d;
这样便做成了即拥有html-loader加载图片的功能,有可以拥有ejs-loader模板语法的loader编译器了
源码可以以直接npm install jcy-loader就可以看到了