Velocity是一个基于Java的Web页面模版引擎。十多年前,Velocity将Java代码从Web页面中分离出来,使得开发者能够并行网页开发和Java开发。随着十年前后端分离的浪潮涌动,回首再面对这些基于Velocity的旧系统,无论是后端还是前端人员维护,都会存在诸多问题:

(1)后端人员维护:不熟悉前端开发模式,需要花费大量精力学习UI和Js框架;

(2)前端人员维护:Velocity渲染依赖Java环境,需要花费大量精力学习Maven工程、环境配置,且前端MVC框架版本老,开发效率低。

这种情况广泛存在于零售内部的一些旧系统中,且业务需求的不断迭代,会导致系统维护成本越来越高。针对需要频繁迭代的页面模块,常见的应对措施是采用前后端分离方案,对页面进行整体重构,但如此以后,整体重构的代价是巨大的,主要体现在如下几点:

(1)需要覆盖所有的业务场景和需求;

(2)缺乏覆盖全场景的测试物料;

(3)页面重构本身不带来业务价值。

我们团队承担了B端业务,由于业务启动时间早,也不可避免需要维护这些Velocity系统。

针对老系统维护难的痛点,我们在实践中探索了一种对老系统侵入程度低、技术架构缓步升级的技术路线,分为4个步骤,分别是(1)搭建Velocity+MVC+MVVC混合架构;(2)建立Velocity单文件组件化能力;(3)创建Velocity本地沙盒环境;(4)Velocity页面前后端分离。下面分别进行详细说明:

一、 搭建Velocity + MVC + MVVC混合架构

Velocity系统多数还在使用JQuery等Js框架,开发效率低,亟待改善。对比MVC框架和MVVC框架,MVVC框架封装了视图层逻辑,开发效率显著提升。

因此第一个步骤是在Velocity页面中引入MVVC框架,实现两套技术架构的共存。我们引入了Vue以及配套的UI组件库,考虑Vue的主要因素有以下几点:

(1)Vue支持Js资源链接的方式引入和使用,即在Velocity页面中加入一行script标签即可实现开箱即用;

(2)Velocity的页面编写语法与Vue的模板语法非常接近。

混合架构内部,模板渲染需要分两步进行: Velocity模板首先在服务端渲染为Vue模板,Vue模板在客户端渲染为最终页面。

混合架构存在的问题是,由于一些Session内关键参数是服务器直出,Vue并不能直接获取到这些参数,因此传参的方案是在页面中提前埋了一些占位符,Vue执行时通过访问DOM来获取。

后续需求迭代时,可以逐步将业务逻辑从老旧MVC技术栈迁移到新的MVVC技术栈中,实现开发、维护效率的提升。

二、 建立Velocity单文件组件化能力

当项目规模较大时,不同模块之间可能存在一些相似的功能或逻辑,摆在面前的问题是如何实现模块级的功能复用。

因此第二个步骤是在Velocity系统中引入组件化能力,实现跨页面代码复用。Velocity系统由于渲染依赖Java环境,难以适用基于NodeJs的前端工程化能力,无法直接使用Vue的单文件组件化能力。幸运的是,可以利用Velocity的包含(#include)和解析(#parse)能力,配合Vue的API接口,实现一种创新型的Velocity+Vue单文件组件化技术。

如果你熟悉Vue,你肯定对Vue单文件组件很熟悉了,即一个文件名以.vue后缀结尾的文件,它描述了一个Vue组件,内部结构的三板斧:template、script、style,简单来说分别描述了组件的模板呈现、逻辑交互、css样式。

Velocity单文件组件的组织方式参照了这个层级结构,使用一个文件名以.vm后缀结尾的文件,描述了一个Velocity组件,由于缺乏工程化的能力,区别点在于:(1)为了兼容低版本浏览器,需要使用script标签来承载模板;不考虑浏览器兼容性的情况下,也可以直接使用template标签。(2)需要手动调用Vue.component执行组件的注册。

实现单文件组件化之后,Velocity页面可以通过粒度更小的组件来层层组装,实现系统的业务耦合程度进一步降低。

三、 创建Velocity本地沙盒环境 + 前端工程化

前面两个步骤对系统整体架构进行了大幅优化,但是仍有一个痛点没解决:Velocity渲染依赖Java环境,习惯了本地开发的前端同学会很无语:改一个小问题需要本地盲开发->在线部署容器->看效果->继续盲修改,一来二去几个小时就过去了。

因此第三个步骤是实现Velocity本地编译和开发环境,并且引入工程化技术实现热更新。

解决Velocity本地编译的核心思路是模拟Server的环境变量,并且支持Velocity语法编译。我们搭建了一套基于Velocity的前端沙盒工程,前者通过在工程中mock服务端变量的方式来实现,在本地JSON数据源承载这些环境变量;后者是基于Velocity语法AST重构,开发了一套解析引擎Velocity-loader,支持在webpack中实时解析文件并注入环境参数。

沙盒能力引入后,开发流程转变为本地实时开发Velocity,热更新达到毫秒级,开发体验只有一个字:爽。

四、 Velocity页面前后端分离

事实上,对比前三个步骤,我们距离Velocity页面彻底前后端分离已经很接近了。

第四个步骤是真正实现Velocity页面的前端独立构建和部署,并永久摆脱依赖Server端渲染。但由于Vue-loader实际上会在工程编译时把模板语法解析成render函数,已经破坏了模板语法的结构,因此不能支持在客户端动态的解析Velocity,需要固化渲染环境变量。Velocity的动态数据渲染部分需要改写为Vue的语法来实现,托靠客户端Ajax来刷新动态数据和页面。

至此,我们完整实现了对Velocity后端应用向前端工程化逐步演进之路,路漫漫其修远兮,吾将上下而求索,也欢迎各位看官共同探讨。

作者:京东零售 陈震

内容来源:京东云开发者社区

Velocity 不用愁!Velocity 系统的前端工程化之路的更多相关文章

  1. 用grunt进行前端工程化之路

    我们的项目wecash4.0的前端构建考虑过用fis和grunt. 目录: 前期调研:fis vs grunt vs gulp? 一.安装grunt和项目. fis是百度fex研发的构建工具,非常方便 ...

  2. Fis3的前端工程化之路[三大特性篇之声明依赖]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  3. Fis3的前端工程化之路[三大特性篇之内容嵌入]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  4. Fis3的前端工程化之路[三大特性篇之资源定位]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  5. 前端工程化系列[06]-Yeoman脚手架核心机制

    在前端工程化系列[05] Yeoman脚手架使用入门这边文章中,对Yeoman的使用做了简单的入门介绍,这篇文章我们将接着探讨Yeoman这个脚手架工具内部的核心机制,主要包括以下内容 ❏ Yeoma ...

  6. 公司内部技术分享之Vue.js和前端工程化

    今天主要的核心话题是Vue.js和前端工程化.我将结合我这两年多的工作学习经历来谈谈这个,主要侧重点是前端工程化,Vue.js侧重点相对前端工程化,比重不是特别大. Vue.js Vue.js和Rea ...

  7. 10分钟学会前端工程化(webpack4.0)

    一.概要 1.1.前端工程化 随着前端的不断发展与壮大,前端变得越来越复杂,组件化.模块化.工程化.自动化成了前端发展中不可或缺的一部分,具体到前端工程化,面临的问题是如何提高编码->测试-&g ...

  8. Velocity初探小结--Velocity在spring中的配置和使用

    最近正在做的项目前端使用了Velocity进行View层的数据渲染,之前没有接触过,草草过了一遍,就上手开始写,现在又回头细致的看了一遍,做个笔记. velocity是一种基于java的模板引擎技术, ...

  9. 前端工程化系列[03]-Grunt构建工具的运转机制

    在前端工程化系列[02]-Grunt构建工具的基本使用这篇文章中,已经对Grunt做了简单的介绍,此外,我们还知道了该如何来安装Grunt环境,以及使用一些常见的插件了,这篇文章主要介绍Grunt的核 ...

  10. 页面仔初窥"前端工程化"

    今天看了几篇前端界的一位大牛--张云龙的文章,其中一篇在自己的理解范围内看得懂一些,有所收获,说的是前端工程化的事,看完算是对前端工程形成了一个模糊的概念. 现在我所接触到的前端开发,还是张云龙大神所 ...

随机推荐

  1. Android笔记--查询联系人

    查询联系人 先在raw_contacts表里面查到每个联系人的不同的id,然后再根据各个id去查询各个联系人的详细信息 然后利用id得到相应的uri的值: 之后,就直接根据uri查询各个联系人的详细信 ...

  2. Z 函数

    简单记一下,避免忘记. z 函数 对于字符串 \(S\),我们将 \(z(i)\) 定义为从 \(i\) 开始的后缀与 \(S\) 的最长公共前缀的长度. \(O(n)\) 求出 z 函数 我们添加一 ...

  3. RPC通信原理概述

    RPC通信原理概述 1.RPC概述 1.什么是RPC RPC(Remote Procedure Call Protocol)远程过程调用协议.它是一种通过网络从远程计算机程序上请求服务,而不需要了解底 ...

  4. 通知短信 API 接入全流程(超详细整理)

    随着移动互联网和智能手机的普及,短信成为了一种便捷.快速且有效的通信方式,尤其在向用户发送重要信息或提醒方面具有很大的优势. 本文将会深入探讨如何在程序中接入通知短信 API 实现短信通知功能,此外, ...

  5. Spring(Bean详解)

    GoF之工厂模式 GoF是指二十三种设计模式 GoF23种设计模式可分为三大类: 创建型(5个):解决对象创建问题. 单例模式 工厂方法模式 抽象工厂模式 建造者模式 原型模式 结构型(7个):一些类 ...

  6. KVM WEB管理工具 WebVirtMgr

    一.webvirtmgr介绍及环境说明 温馨提示:安装KVM是需要2台都操作的,因为我们是打算将2台都设置为宿主机所有都需要安装KVM相关组件 github地址https://github.com/r ...

  7. ES_ChatGPT问答

    Q1:springboot项目,如何使用elasticsearch的api增删改查?查询中有哪些方式,如果模糊查询.排序查询.分页查询?分别阐述下这些查询方式的用法?最后举一个完整的例子 答: 在Sp ...

  8. MySQL(十)表空间结构:区、段与碎片区

    表空间结构:区.段与碎片区 为什么要有区? ​ B+树中的每一层的页都会形成一个双向链表,双向链表之间的物理位置可能会离得非常远,当遇到范围查询的适用场景的时候,就会定位到最左边和最右边的记录,然后沿 ...

  9. APISIX 是怎么保护用户的敏感数据不被泄露的?

    本文以 APISIX 作为例子,为大家介绍了如何借助 Global Data Encryption 功能来保护敏感数据,确保不会有任何敏感数据进行明文存储,这样即使 etcd 中所有存储的数据都被盗取 ...

  10. JavaFx 实现水平滚动文本(跑马灯效果)

    原文地址: JavaFx 实现水平滚动文本(跑马灯效果) - Stars-One的杂货小窝 本文是以TornadoFx框架进行编写,各位使用JavaFx可以参考 代码已经封装在common-contr ...