用React重写Tomcat中的前端项目
前言
最近接到一个活, 问我能不能调整这么个页面的导航栏, 项目是跑在Tomcat
中的.
因客户原因, 项目展示图不给放了, 请自行脑补一个带侧边栏的后台管理系统.
我都不知道啥是Tomcat
, 花十分钟官网下了个demo, 起了个服务, 看了看依然还都是基础的html + css
, 就应了下来.
一期很快很顺利, 就是写jQuery操作操作dom
, 加一些样式复写. 一顿操作猛如虎, 还交了文档表示如何最小程度影响老的代码, 客户很满意. 问我能不能重写前端. 因为现在交出去的html文件很原始, 他一个外行都能靠devtool
找到html与css文件操作一番, 这是一个部在局域网的项目, 希望交出去能有一些保密性.
呵, 小小项目, 我还能做不了?
困难
当然, 靠谱如我当然没有直接应下来, 因为没有后端文档, 后端也动不了, 只有Java编译后的class
文件.
Tomcat配置
我也几乎不懂, 所以, 我先调研评估了一下. 主要两个问题能解决就行:
- 生产环境部署
- 登录验证
也是本博客主要想写的东西.
打包部署
我们现代React, Vue等常见的SPA
部署方案, 无论是Nginx
, 还是用Vercel
, 都是需要启动专属前端的服务解决前端路由的问题.
而在我们的项目中, 因为Tomcat本身已经是个服务了, 他服务直接就启在部署后的80
端口上, 在之前的项目里, html
资源的加载与路由全部都由java
服务操控.
Tomcat
能不能启两个端口的服务再说, 这个项目的接口访问是不允许跨域的. java
动不了, 所以我的决定方案是
用NextJS
的静态导出
.
解决跨域
单纯的解决跨域手段有挺多, 最简单的是next.config.mjs
中的rewrite()
, 但是我主要面临的难点是set-cookie
, 需要同源才能使得登录session
生效.
所以本地另启nginx
, 或express
等做代理转发并无效, 因为代理转发的服务端口和我开发环境的3000
端口必然又是跨域.
解决setCookie
不能再起一个端口转发, 那我直接3000
端口自己转呗.
这一点NextJS
不如Create-react-app
和Vue-cli
, 这两个都自带了proxy
配置, config设置下就可以自身端口转发了.
这个需要自己写个proxy.js
, 启动的话用node proxy.js
, 等于在原始的next dev
外面包了一层拦截转发, 代码如下:
const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.use((req, res, nextStep) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
if (req.method === 'OPTIONS') {
res.sendStatus(200)
} else {
nextStep()
}
})
// set proxy middleware
const apiProxy = createProxyMiddleware({
target: 'http://localhost:8080', // replace to your own backend api address
changeOrigin: true,
pathRewrite: {
'^/api': '' // the proxy path replacement
}
})
// all the request starts with '/stream/api' will proxy to your target backend server
server.use('/api', apiProxy)
// return all the rest request to Next.js
server.all('*', (req, res) => handle(req, res))
// server port
const PORT = process.env.PORT || 3000
server.listen(PORT, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${PORT}`)
})
})
解决Cookie中带path
他不光用set-cookie
, cookie还带/path
参数. 也就是说我得给他整个匹配的相应的path才能搞定.
这个方案NextJS
里倒是现成的, 开发环境在next.config.mjs
里配置basePath
即可.
生产环境的话, 既然导出就是静态文件, 加个path
的文件夹包裹, 前缀自然就有二级路由了.
老项目亮点
在老的堆html
的项目中, 无法有全局组件的概念. navbar
, footer
这种组件每次页面需要跳转后需要重载.
改写的这个项目对a链接跳转拦截
, 利用iframe
作为容器加载新的html, 挺有意思.
UI重写调研
项目干了两期.
第一期因为工期太紧, 十几个接口, 没文档只靠看老代码, 4天干完. 所以完全保持原样式库, 主要是基于Bootstrap5
的tabler.css
.
第二期, 客户想要换套UI, 没有设计让我看着整. 那我这不得趁着这个付费实操的机会好好熟悉一下Tailwind
?
我调研搜索了一下, 给挑了Tailwind
系的比较高star的几个UI库.
不知道为啥感觉很像中国同胞设计的daisyui 这个是比较纯的html样式库, 自己写React组件的话, 可定制强度会大一些.
最后当然还有tailwind官网自己的那套, 我是没咋看上.
后来我选了NextUI.
叨叨两句Tailwind和Bootstrap
我之前一直是用styled-component
手搓css, 这次小项目恰好让我有机会对这两个作为样式封装
UI库的顶流, 直接横向比较一番.
Bootstrap存在很多年了, 扎实好用, 但是没有像Tailwind
突然爆火, 我觉得Tailwind的火一大部分是靠其系列的ui库带起来.
而Bootstrap的衍生UI库没那么多, 主要还是他的那套!important
原则, 让各种样式类很难叠加再次创造新的样式库.
原来在公司code review, 都建议同事非必要不要写!important
, 不要写内联
, 因为后期再改动或更新, 确实很头疼.
最后项目
因客户原因, 最后展示图不给放了, 请自行脑补一个带light/dark切换的, 很酷炫的新页面.