本文由做者郑海波受权网易云社区发布。html
前言
我这里就不介绍requirejs了, 简而言之: requirejs是支持AMD规范的模块加载器, 事实上它也是AMD的最直接推进者。node
如今可供挑选的开源模块解决方案不少,好比component、cjs+browserify、umd等等,可是无疑相似requirejs这类加载系统是如今最成熟和可靠的解决方案,因此regularjs第一步就是提供对requirejs的插件支持。jquery
requirejs的插件体系
requirejs的源码内部预留了hook,使得你能够建立插件来加强这个模块系统,而且这个插件能够作到影响到你的OPTIMIZER阶段,一些资源能够被处理为标准的AMD模块。webpack
插件广泛被用来es6
预编译web
加载非js文本express
lint 或 test 后置或前置的操做 等等npm
example 好比它自己是不支持加载文本信息的,可是你能够经过text!插件来加载。json
require(['text!foo.html', 'jquery'], function(foo, $){gulp
$('#anchor').html(foo);
})
须要注意的是因为文本没法用script标签进行加载,因此text内部是经过XHR来载入的,即它会受到同源策略的影响。
优化OPTIMIZER
因为requirejs同时提供工具(npm:requirejs)能够静态打包优化AMD,刚才的那个text!foo.html会同时被text插件转换为相似下面的AMD模块结构
define('text!foo.html',[],function () {
return '<h2>早上好\n</h2>';
});
requirejs的插件实际上是一个实现的特定接口的标准AMD模块,它在定义时与其它业务模块并没有区别。
例如官方text插件的源文件
define(['module'], function (module) { 'use strict'; var text = {
load: function(){} .... } return text
})
其中load等接口是插件必须实现的,
对于各个接口描述我就不细究了,你们能够参考官网
顺便列举一些有用的requirejs插件
text插件(最经常使用插件) 若是你的文本内容无需在打包优化阶段作处理,几乎均可以使用这个插件来完成加载
json插件 比楼上多作了一步JSON.parse.
amd-loader(好东西): 注意不要requirejs自己弄混了,由于requirejs自己不是基于xhr的,这个插件主要是提供完善的xhr支持来加载文本内容。一句化即它是[插件的loader插件],做者过后才发现有这么一个插件...绕了很多弯路。具体例子能够查看es6
handlebars 用来加载handlebar的插件
其实因为amd等模块系统占据了开发中的模块入口这一环,其实在开发中能够有无限的可能性,这也是常规大公司都会自造一个轮子来最优配置的原因之一,事实上requirejs目前的插件系统已经有足够的灵活性来定制本身的策略。
实现requirejs-regular的过程
背景
首先咱们先理清咱们的需求, 与常规的的模板预编译相似,咱们的插件主要为了实现两个功能。
在开发阶段,咱们但愿能加载js文件同样,加载咱们的模板文件,这带来的几个好处
这使得咱们没必要将模板零散的填充到页面的script 或 textarea标签中
依赖系统惟一化, 模板依赖集成进了模块依赖中
在优化阶段(即requirejs提供的OPTIMIZER的上线打包功能),咱们的模板字符串能够被预处理为序列化的AST对象,这样就不会发生浏览器端的解析,效率更高。
实现
一个插件模块会同时跑在浏览器端(开发环境)和node端(为线上或测试环境的打包优化工具),因此你的插件模块必须能够同时跑在浏览器端和node端,这个几乎是整个开发环境最麻烦的一部分
regular.js的单文件虽然是umd模块能够支持amd环境,可是因为依赖的dom。因此首先要将parser部分(不依赖dom)打成一个AMD模块,因为regularjs自己就是基于commonjs的模块构建,将其中一部分打成AMD模块是分分钟的事情,这里咱们使用webpack来打包成regular-parser.js,简单起见咱们随regularjs模块一同发布到bower上
咱们还要解决模板的加载问题,插件内部的加载问题也要手动解决,即你至少要实现loader接口和get接口。这里咱们彻底能够偷个懒,直接使用!text插件。
即插件会依赖这两个模块
define(['text', 'regular-parser'], function(text, parser){ //blalalalala...
return{ load: load, write: write }
})
而后咱们只须要实现两个接口:
load
var buildMap = {};function load(name, req, onLoad, config){
text.load(name, req, function(data,r){ onLoad( (buildMap[name] = parser.parse(data, false)) ); }, config);
}
这里直接使用了text插件的纯文本加载,须要注意的是这个onLoad接口,传入参数至关于模块的内容,咱们这里预parse了这段文本内容。即你经过rgl!template.html最终会得到解析后的AST数据。
其实对于regularjs来说在浏览器端有无进行模块系统层面的预解析并没有意义,关键是在打包优化阶段。这里的buildMap主要是为了保存这段内容用于打包使用。
write 实现write接口主要是为了在打包优化阶段改写相关模块
var tpl = function(str, data){ return str.replace(/{{(w+)}}/g, function(all, name){ return data[name] || ""
})
}var template ='define("{{pn}}!{{mn}}",function(){ return {{ast}} });n';function write(pn, mn, writeModule){ if(buildMap[mn]){
writeModule( tpl(template,{ pn: pn, mn: mn, ast: parser.parse(buildMap[mn]) }) )
}
}
此时这个插件必须依赖于两个模块,即必须同时保证text和regular-parser模块同时存在,相似的方案能够查看hogan,它必须保证环境中有hogan和text才能够运行. 熟悉requirejs打包过程的同窗也知道,除了loader端的配置,咱们在build的打包文件也须要一并将这些依赖模块剔除,由于上线时是不须要这些插件的。因此这将大大增长配置成本,其实解决方案也很简单,就是使用[webpack]再将其打包成一个standlone的AMD模块便可,具体能够参考这里的gulpfile。
大功告成
使用就很是简单了,和你使用requirejs-text差很少,
1.首先下载rgl.js,最简单的就是bower安装
bower install regularjs-regular --save
save参数是安装后并写入到bower.json中,这个和npm一致
2.配置
require.config({ paths : { "rgl": '../../bower_components/regularjs-regular/rgl',
// 同时载入咱们的regularjs来使用这些模板 "regularjs": '../../bower_components/regularjs/dist/regular'
}
});
3.使用
require(['rgl!./foo.html', 'regularjs'], function( tpl, Regular){ var Foo = Regular.extend({
template: tpl }) new Foo({}).$inject("#app")
});
4.打包
模板文件<h2>{{message}}</h2>通过插件处理后会打包成
define("rgl!foo.html",function(){return [{"type":"element","tag":"h2","attrs":[],"children":[{"type":"expression","body":"_c_._sg_('message', _d_['message'])","constant":false,"setbody":"_c_._ss_('message',_p_,_d_, '=')"}]}] });
即上线后就不会有parse了,好比PO主目前正在开发的项目在初期就有几十个模板文件,build成单文件后的运行时开销仍是应该尽可能避免.
tip:build.js记得经过stubModules配置项目删除掉这个插件模块,具体看demo的build.js。
对于NEJ的使用者
NEJ的新模块系统支持上述相似的regular模板加载了
网易杭州的同事,事实上你已经能够在NEJ的新模块系统中(彻底兼容老版本)经过regular!path/to/template.html的方式来加载你的regular模板了,打包以后模板将会被预解析,同时新版NEJ也支持text!加载纯文本内容, 详询@飞锅。新版本的加载系统,支持相似AMD的注入写法,而且兼容老版本的模块写法,亲测好用哈。
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请访问网易云社区。
文章来源: 网易云社区