nodejs:解决传统开发模式的前后端"分离"问题

最近接触到两个小项目,是用传统的开发方式,由服务端渲染页面,前端用到thymeleaf和jsp

虽然笔者也可以按照项目的架构搭一个阿帕奇服务器把java项目跑起来,但无疑是费时费力的,可能做完这两个项目换别的技术架构时,这个环境就没用了,又得装别的环境才能跑页面。而且在电脑装太多环境,电脑负担也很重。

有没有别的办法?我首先想到的是nodejs。

所谓传统开发,一般就是把静态页面先写好,等后端把页面路由弄好了,再将这些静态页面改成jsp等形式放到项目中。这些“套”好的页面,脱离了环境单独打开是不能查看的。这给分离开发带来了不便。

但我们可以用nodejs模拟一个服务,提供接口和测试数据,页面模板则使用nodejs第三方插件包转换一下,返回给前端。与搭建其它服务器相比,nodejs环境配置和建服务器更快速,切换模板引擎也更方便。虽然也涉及一些后端知识,但nodejs使用javascript,前端付出的学习成本更低。

下面说说如何搭建一个项目。

1搭建express服务器。

这里为了方便,我使用了应用生成器。

npm install express-generator -g

express server
cd server
npm install

为了更改项目后能自动重启服务,建议安装supervisor插件

npm install -g supervisor

打开package.json,更改start命令:

{
  "name": "server",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "supervisor ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.9",
    "express": "~4.16.0",
    "http-errors": "~1.6.2",
    "jade": "~1.11.0",
    "morgan": "~1.9.0"
  }
}

运行项目

npm start

打开浏览器http://localhost:3000

相关信息参考express官方网站

2 静态文件路径修改

通常传统的开发中,项目的页面也会放在一个固定的文件夹里,为了避免迁移时的不便,文件夹的结构应当保留,这需要在express服务器中做相关修改。

例如项目的文件放在project文件夹中,static存放静态文件,templates存放页面


搜狗截图18年08月31日1051_1.png

首先配置静态文件路径

在app.js中修改

app.use(express.static(path.join(__dirname, 'project/static')));

3 模板插件

你能从上图看到home文件夹中有两个文件:
index.html使用的是thymeleaf模板,index.jsp使用的是jsp模板。 事实上你可以在这个项目中同时解析n种模板。

在express的官方文档中提到。

和 Express 兼容的模板引擎,比如 Jade,通过 res.render() 调用其导出方法 __express(filePath, options, callback) 渲染模板。

有一些模板引擎不遵循这种约定,Consolidate.js 能将 Node 中所有流行的模板引擎映射为这种约定,这样就可以和 Express 无缝衔接。

然而在 consolidate.js 插件文档中可以看到,并不支持thymeleaf和jsp模板
https://www.npmjs.com/package/consolidate

所以我们不能用express的render函数,改用直接读取文件,通过第三方插件转换的方法。

我们能很容易找到jsp和thymeleaf的npm 模板插件

jsp-js https://www.npmjs.com/package/jsp-js?activeTab=readme

thymeleaf https://www.npmjs.com/package/thymeleaf

安装模板引擎

npm i jsp-js --save
npm i thymeleaf --save

4 修改路由

路由非常关键,因为解析模板的代码都在这里,但你也可以另起文件处理,这里只是为了描述方便放在同一文件中。

在routes/index.js中加入:

var express = require('express');
var router = express.Router();
var fs = require('fs');
var path = require('path');
var relativePath = '../project/templates/'
// thymeleaf
var thymeleaf  = require('thymeleaf');
var thymeleafTemplate = thymeleaf.TemplateEngine;
var StandardDialect = thymeleaf.StandardDialect;

var templateEngine = new thymeleafTemplate({
  dialects: [
    new StandardDialect('th')
  ]
});
function getThymeleaf(filePath, params, handle) {
  var html = fs.readFileSync(path.join(__dirname, relativePath,filePath), {
    encoding: 'utf-8'
  });
  html = handle(html);
  return new Promise((resolve,reject) => {
    templateEngine.process(html, params)
    .then(result => {
      resolve(result)
    });
  })
}
//jsp
const JSPJs = require('jsp-js').Renderer;
const jsp = new JSPJs({
  root: [path.join(__dirname, relativePath)]
})
function getJsp(filePath, params, handle) {
  return new Promise((resolve,reject) => {
    var html = jsp.render(filePath, params);
      html = handle(html);
      resolve(html);
  })
}

router.get('/thymeleaf', function(req, res, next) {
  getThymeleaf('home/index.html', {
    name: 'thymeleaf',
    img: '/img/default.jpg'
 }, function(html){
  // 对读取到的页面进行预处理,以解决特殊问题,如  html = html.replace("${type}!='manage'", "true")
   return html
  })
  .then(result => {
    res.send(result)
  });
});
router.get('/jsp', function(req, res, next) {
  getJsp('home/index.jsp', {
    name: 'jsp',
    img: '/img/default.jpg'
 }, function(html){
  // 对读取到的页面进行预处理,以解决特殊问题,如 html = html.replace("<%=type!='manage'%>", "true")
   return html
  })
  .then(result => {
    res.send(result)
  });
});
module.exports = router;

在实际使用中,笔者发现thymeleaf还是有些语法不能解析,因此在getThymeleaf函数和getJsp函数中加了一个handle参数,参数可以传入一个方法,对拿到的文件字符串进行处理,将需要解析的语法整串替换掉再返回,虽然粗暴,却也节省时间。

index.html 页面内容




    
    
    
    Document


    
    

index.jsp页面内容




    
    
    
    Document


    
    <%=name%>


你能看到两种模板都成功解析了。


menu.saveimg.savepath20180831115240.jpg

5.修改及迁移

如果后端已经“套”好页面,但样式需要修改,或者页面新增一些内容,你拿到项目文件之后,只需在express中做一些简单的配置就能把页面跑起来,而且你无须更改页面已经写好的逻辑。做完修改后,后端把页面放在项目中就能运行。
当然,严格来说,路由需要后端去写,这就不算是完全的前后端分离了。只是前端使用Nodejs模拟出一个服务,后端就无需关注前端页面,前端也不用等后端套页面时才发现问题。
然而将“套”页面的工作交给前端做,前端还需要熟悉该模板的语法,并且在建造模拟数据时要与后端沟通。

相关代码可从github上获取:
github地址

你可能感兴趣的:(nodejs:解决传统开发模式的前后端"分离"问题)