作者:曹阳、王歆宇
1.目前已知regular模版中双大括号会被编译,导致返回错误的AST,可以在最外层加上v-pre
,若有使用r-class、r-style就必须加上,其他场景最好也加上
示例
<rc ref="rc" :revent="REvent" :rdata="RData" :rfilter="RFilter">
<div v-pre>
<ux-button value={name} on-click={this.clickBtn($event)}></ux-button2>
</div>
</rc>
2.需要注意函数中this的指向,vue事件指向vue,regular事件指向regular
3.在regular模版中,若在逗号后面包含空格,如 on-click={this.xxx(item, $event)}
,会导致AST格式出错,解决方案是把空格去掉,或者大括号外加上引号
为了在vue中支持regular,我们可以注册一个RC组件来承载,它是一个vue组件,通过vue slot(插槽)获取模版,绑定data、event、filter,动态生成regular组件插入到视图层,从而支持了在vue组件中直接编写regular代码的功能。
因为我们的项目是采取weex控制组件的各个state,即单向数据流来控制组件中的数据,但是在目前已实现的组件池基本已被regular双向绑定给限制了,虽然也可以在watch中触发commit,dispatch,可这也无疑会将逻辑打乱,因此,针对这部分代码,我们大多没有采用weex管理状态,而交由组件自身去维护,有时候享受不了单向数据流带来的便利性。
我们可以看到,我们通过Babel将完成了对NEJ模块依赖的解耦,通过Vue组件代理,完成了regular组件上的兼容,最后就是去解决如何上线部署了
1.【卡搭校园】这个项目,后端还是按照以往的逻辑,将一些后端数据直接写到ftl模板之中。也就是说,最后上线,我们仍然依赖freemarker去解析数据。但是,我们在使用webpack构建开发环境之时,其本质是不支持渲染java模板的。因此,在构建环境,我们要区分开发状态以及上线打包状态,提供不同的代码用来兼容不同平台(node or html/ java)
先来看看第一个问题,在webpack-server中,默认是通过HtmlWebpackPlugin插件生成自动生成html,同时,该插件可以兼容ejs语法对各种环境进行定制。那么,我们也可以通过他自动生成ftl模板。webpack配置如下
let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'));
let conf = {
// 模板来源
template: '!!ejs-compiled-loader!' + filePath,
// 文件名称
filename: filename + '.html',
// 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
chunks: ['manifest', 'vendor', filename],
inject: true
};
// 生产环境转为ftl
if (process.env.NODE_ENV === 'production') {
conf = merge(conf, {
filename: filename + '.ftl',
env: 'production',
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
});
}
对应的html模板如下所示
<% if(htmlWebpackPlugin.options.env === 'production'){ %>
<!--生产环境-->
<script>
<#if webUser?exists>
window.webUser = {
<#if webUser.id?exists>id: "${webUser.id?html}",</#if>
end_key: "end_value"
};
</#if>
</script>
<%} else{%>
<!--开发环境-->
<script>
window.webUser = {
"id": 123456
};
</script>
<%} %>
因为在webpack插件中,我们指定了template通过ejs-loader来渲染,因此我们通过参数传递到html中,通过不同的环境模式,来切换开发环境以及部署到服务器与后端渲染的ftl模板,后期如果有新的后端数据需要渲染到ftl上,只需要维护自己的template模板即可。这样处理也带来了另外一个好处,我们在html模板会使用类似如下的语法
<body>
<div id="app"></div>
<% include src/pages/common/footer.html %>
</body>
插件最后生成ftl时会将所有片段组装到一起,避免了ftl语法 <#include> 部署后路径,资源以及模板被缓存等问题
第二个问题即静态资源服务器替换问题,正常情况下,webpack打包的js||css等都可以通过配置output添加对应的静态资源路径,但是如果出现在HtmlWebpackPlugin模板中的静态资源默认是不会添加,我们不可能在开发或者部署的时候手动添加对应的前缀来满足业务上的需求,因为没有找到合适的工具,因此,在自动切换层,我们手动编写了webpack插件来进行解决。
解决思路如下 通过监听 html-webpack-plugin-before-html-processing 对输出的html进行处理,如果发现他没有带静态资源路径名,则给其增加前缀,示例代码如下
function AddStaticServer (options) {
let option = options || {
serverPath: '//kc.stu.126.net'
};
this.serverPath = option.serverPath;
}
AddStaticServer.prototype.apply = function (compiler) {
compiler.plugin('compilation', (compilation) => {
compilation.plugin(
'html-webpack-plugin-before-html-processing',
(data, cb) => {
data.html = generatehtml(data,html)
cb(null, data);
}
);
});
};
webpack对应配置
plugins:[
.....,
.....,
new AddStaticServerPlugin({
serverPath: config.build.assetsPublicPath
})])
]
在前文解决方案中提到,我们为了区分线上ftl文件以及前端html文件,需要针对性的编写模板,并且通过配置,当遇到通用ftl数据过多的情况下,需要做很多的额外配置以及编写,项目到后期的话也可能会越来越大,因此,在我们的项目中,除了约定必须的model数据外,其他都通过异步接口进行获取,这样也是为了减少后期可能SSR的成本
原有项目中,我们可以通过网易内部的NEI平台来进行接口mock甚至是ftl的渲染,而在新的工程中,因为开发环境的切换,不在使用ftl作为承载页面进行,因此,需要寻找其他方式进行Mock, 好在webpack-dev-server能够提供这样的能力我们可以配置proxy来对接口进行代理,示例代码如下所示
devServer: {
proxy: {
'/api': 'http://localhost:8002/',
'/j':'http://localhost:8002/',
}
}
nei默认会在8002下启动mock服务器,因此,在开发环境中,我们可以像以往一样,使用nei平台对接口和数据模型进行管理,最后我们只要将webpack-dev-server的接口代理到nei下即可。同样,我们也可以在开发环境中随时更换成线上服务器(需要解决csrf以及cookie的问题),用本地访问真实的数据也成为了可能。
目前,该套方案已经成功运行上线了一段时间,也得到了组内同学的认可,同时,该方案并没有对NEJ,Regular源码进行改造,可以随时切换成以NEJ为主的构建方式。不过,依旧还是有许多地方可以优化,比如
相关阅读:VUE & Regular & NEJ 无痛融合解决方案(上篇)
网易云大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经田翔授权发布。