虽然2月初就回来了,可 CoreCRM 一直到5月才开始恢复开发,期间是各种生活中的意外和不方便。

1. 为什么要重构

首先是一件很值得高兴的事情:CoreCRM 有了第一位 contributor!Larry 是我原来的一位实习生,现在在某公司做前端开发。因为 Larry 的加入,我就不再是一个人战斗了。当然,也就得考虑怎么进行合作的事情了。

年前的开发计划是:使用 Bootstrap 按照悟空CRM的样子先弄出一个可以用的版本来。然后再使用一些比较好的后台前端框架来代替 Bootstrap。在和 Larry 讨论之后,他觉得 Bootstrap 已经有点跟不上时代,以后扩展 UI 都会有一些困难。加上 Bootstrap 是 jQuery 作为交互基础的,和 VueJS 这样的框架也是不太配合。正好 Larry 的公司正在使用蚂蚁金服出品的 Ant Design 开发后台程序,他感觉这个框架设计的不错:组件丰富、设计合理、社区活跃、文档丰富(还是中文)。Ant Design 基于 React Component,也是当前非常流行的前端框架,经过多年的发展,据说其组件的丰富程度已经与 jQuery 不遑多让。

鉴于之前我使用 VueJS 做全页渲染的经验,我认为 React 这东西,如果不做 Server-Side Rendering(SSR),用户体验不会太好。如何集成 SSR,其实有两种方案:

  1. 完全使用 nodejs 来做前端服务器,ASP.NET Core 做 API 服务器
  2. 集成 node 到 ASP.NET Core 里,通过 ASP.NET Core 提供一些 Web 的服务

去年我也曾经用了一周的时间去研究几个 ASP.NET Core 的 React Server-side Rendering 方案,可一个人的精力毕竟有限,要同时使用两种语言开发,脑子的转换效率是一个问题。最后我放弃了 React,转而使用 ASP.NET Core 的 Razor 来做页面渲染了。只对其中一些动态的部分做了 VueJS 组件。不过这次情况不一样了,有 Larry 做前端的开发,我可以把更多的精力放到后面的API 开发和架构的优化上。而且,前后分离之后,还可以在对方工作滞后的情况下继续开发。所以我决定对整个项目进行重构。

2. 重构的尝试

近些年前端技术发展迅速,各种 hot reload 横行,在开发的时候要方便和高效的多。那么应该怎么来实现 SSR 呢?我进行了三次尝试:

2.1 Microsoft.AspNetCore.SpaServices

做为 ASP.NET Core 团队的作品,感觉上是比 Facebook 做的 ReactJS.NET 更好用一些。特别是和 ASP.NET Core 的互通性上,应该有一些优势。不过,ReactJS.NET 的 SSR 已经内置,写起来要容易一些。

一开始,我尝试使用 aspnetcore-spa 这个 yeoman generator,可这货居然还是使用的 typescript 做为主语言。虽然我之前也学了一点 typescript,但与别人合作的时候,就不能只考虑自己的技术栈了。为了不增加 Larry 的学习成本,以使得项目能够尽快进入开发,我决定还是自己搞一个基于 es6 的 ClientApp。方法当然也很简单:用 dva-cli 创建一下就 OK 了。

在完成了 ClientApp 的创建之后,需要添加一个 boot-server.js 来实现 SSR:

var { match } = require('react-router');
var { createServerRenderer } = require('aspnet-prerendering'); module.exports = createServerRenderer(function(params) {
return new Promise(function (resolve, reject) {
var re = /^\/([^\/]*)(/[^\/]*)?/;
var matched = params.location.path.match(re);
var controller = matched[1];
var codeFile = './dist/' + controller;
var App = require(codeFile); // eslint-disable-line var path = matched[2] === '' ? '/' : matched[2]; // this line is buggy.
match({
routes: App.routes,
location: path
}, function (err, redirectLocation, renderProps) {
if (err) throw new Error("Route match failed: " + err); if (redirectLocation) new Error("I don't know how to redirect."); var initialState = {};
resolve({ html: App.renderHTML(initialState, renderProps)});
})
});
});

params 里包含了一些从 Razor 传进来的数据,比如访问的路由、初始化数据等。这里本来应该直接使用 params.location.path来匹配路由,进行渲染的,可是我并没有使用完全的 SPA (Single Page Application) 架构,而是有所分离,所以就需要使用正则表达式分离 controller 和 action,然后再进行页内的匹配。现在 repo 里的代码只是实现了单页的测试载入,还没有正式的使用起来。

2.2 koa + Web API Server

本来以为上面这个方案就已经可以了。前端使用了 dva + antd + roadhog,可以直接运行一个 webpack-dev-server 直接进行开发。然后我再转到 Razor 里做为一个 Controller 的 View。不过,Larry 希望能完全脱离 ASP.NET Core 运行前端代码。我也考虑了使用

SpaServices 可能会有一些限制,比如:需要处理路由、不能使用 ES6,同时运行的时候也还是需要安装 Node,其实和一个独立的前端 Server 并没有什么区别。所以我又尝试把前端的 Server 完全分离出来。

这一步可能做的有点太激进了,我尝试使用 Web API 的模板重新创建了 CoreCRM 这个 project。结果就悲剧了:Web API 是非常轻量的框架,里面什么也没有。加上如果要分离前后端 Server,比较好的权限验证方案是使用 JSON-Web-Token,不然还需要在两个 Server 之前同步 session,也是比较麻烦的事情。而搞一套 JWT 的验证机制,也不是很容易。已经有的解决方案不是太简单,就是太复杂……

回归 SpaServices

上面这些困难加起来,让我觉得这里面的学习成本现在不可接受。所以就先放弃了这个方案。在经过一点设计和开发之后,我发现这其实和使用 koa 并没有太大的差别。问题总是可以通过一些服务间的交互来解决的。只是现在这个节点,使用 SpaServices 更容易上手一点。待到项目有一个可用的版本,后面可以尝试以其它的方式进行重构,也不是不可能的事情。毕竟这个项目至少还有2.0版。

3. 经验

“选择”总是一件很困难的事情。特别是每个选项都各有利弊的时候,选择就更加困难。每一种组合都是一种可能,每一种组合有都有它的局限。差别可能就在团队成员之间是不是能顺畅的合作。如果合作出现问题,能不能及时调整。

希望这次调整能给项目带来更多的活力。

CoreCRM 开发实录 —— 前后端分离的重构的更多相关文章

  1. Angular企业级开发(9)-前后端分离之后添加验证码

    1.背景介绍 团队开发的项目,前端基于Bootstrap+AngularJS,后端Spring MVC以RESTful接口给前端调用.开发和部署都是前后端分离.项目简单部署图如下,因为后台同时采用微服 ...

  2. 无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离

    近年来,前后端分离已经成为中大型软件项目开发的最佳实践. 在技术层面,前后端分离指在同一个Web系统中,前端服务器和后端服务器采用不同的技术栈,利用标准的WebAPI完成协同工作.这种前后端分离的&q ...

  3. Django系列---开发三 前后端分离

    数据交互接口规范REST,全称 Representational State Transfer,意为"表现层状态转化". django的第三方拓展--django-rest-fra ...

  4. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史

    ---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...

  5. 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) - 介绍

    项目简介 novel 是一套基于时下最新 Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的学习型小说项目,配备详细的项目教程手把手教你从零开始开发上线一个生产级别的 J ...

  6. 前后端分离(手)-- 使用mock.js(好样的)

    ## 前言: 本篇博文昨天七夕写的,一天下来被虐得体无完肤,苦逼的单身狗只能学习,对!我爱学习,关掉朋友圈,并写了一篇博文发泄发泄.这次写mock.js的使用,能使前后端分离,分离,分离,重要的是说三 ...

  7. 《Spring Boot 入门及前后端分离项目实践》系列介绍

    课程计划 课程地址点这里 本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 个部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 项目实践开发 ...

  8. SSM框架中的前后端分离

    认识前后端分离 在传统的web应用开发中,大多数的程序员会将浏览器作为前后端的分界线.将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端. ...

  9. 前后端分离(手) -- mock.js

    前言: 本篇博文昨天七夕写的,一天下来被虐得体无完肤,苦逼的单身狗只能学习,对!我爱学习,关掉朋友圈,并写了一篇博文发泄发泄.这次写mock.js的使用,能使前后端分离,分离,分离,重要的是说三遍. ...

随机推荐

  1. PHP的简单易懂文件管理,可实现基本功能

    我们利用的是嵌入PHP代码和ajax结合的方式,首相想到的是利用遍历文件的方式找出分件下的目录和文件,并且找到它们的路径,使用 dirname取上级目录, basename从完整路径中取文件名,其中最 ...

  2. windows phone 8.1开发:磁铁|Tile更新

    原文出自:http://www.bcmeng.com/tile/ 上一篇给大家分享了toast通知操作的方法,这一篇文章我们就来看windows phone 8.1开发中的磁铁更新.磁铁是window ...

  3. Screen的简单使用

    第1步:新建窗口 输入: screen [-S <作业名称>] 第2步:随便干些什么 在窗口中执行任意命令,干什么都行 第3步:挂起窗口 Ctrl + a d 第4步:还原窗口 scree ...

  4. Nagios工作原理

    图解Nagios的工作原理 Nagios的主动模式和被动模式 被动模式:就如同上图所显示的那样,客户端起nrpe进程,服务端通过check_nrpe插件向客户端发送命令,客户端根据服务端的指示来调用相 ...

  5. 原生JS实现弹出窗口的拖拽

    上一篇说了一下弹出窗口功能的实现思路,一般情况下紧接着就会需要做到弹窗的移动,当然现在有很插件.库比如hammer可以使用,效率也非常好.但我觉得还是有必要了解一下原生JS的实现思路及方式,如下: 思 ...

  6. WebServiceWSDLWeb

    WSDL 文档仅仅是一个简单的 XML 文档. 它包含一系列描述某个 web service 的定义. WSDL 文档是利用这些主要的元素来描述某个 web service 的: 元素 定义 < ...

  7. 浓缩的才是精华:浅析GIF格式图片的存储和压缩

    成文迪, 在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦. GIF格式的历史 GIF(Graphics Interchange Format)原义是"图像互换 ...

  8. 老李分享:HTTP协议之请求和响应

    老李分享:HTTP协议之请求和响应   HTTP请求头详解: GET http://www.foo.com/ HTTP/1.1 GET是请求方式,请求方式有GET/POST http://www.fo ...

  9. Spring事务管理的实现方式:编程式事务与声明式事务

    1.上篇文章讲解了Spring事务的传播级别与隔离级别,以及分布式事务的简单配置,点击回看上篇文章 2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理) Spring实现编程式事务,依赖 ...

  10. Java中的排序方法

    冒泡排序法 快速排序