creeperyang / blog

前端博客,关注基础知识和性能优化。
MIT License
2.63k stars 211 forks source link

怎么用Vue.js改造(大型)传统PHP网站? #42

Closed creeperyang closed 6 years ago

creeperyang commented 6 years ago

接手的项目是维护了很久的老项目,一个传统网站,后端是PHP,前端以PHP模板+jQuery为核心。项目后端代码文件结构还算清晰:

application
├── config
├── controllers
├── errors
├── helpers
├── models
├── service
├── third_party
└── views
    └── page
        ├── index
        ├── user
        └── weixin

前端部分:

front
├── output
├── page
│   ├── index
│   ├── user
│   └── weixin
├── static
│   ├── index
│   │   └── img
│   ├── user
│   ├── util
│   └── weixin
└── widget
    ├── footer
    │   └── img
    ├── header
    │   └── img
    ├── layer
    ├── notice
    │   └── img
    └── pager

目录树省略了部分,但已经可以看出来,各个文件夹按部就班,就是传统的PHP项目。

项目开发测试流程:前端模板部分编译到后端views文件夹;前端其它部分直接编译上传到CDN,同时输出一个静态资源表(json文件:本地路径到CDN路径的映射),这个JSON被fis利用来替换模板中的资源路径。

整体来说,对前端而言,这是一个以PHP模板为核心的传统网站项目,而其中的一些问题应该也是许多还在维护老代码同学碰到的共性问题,本文更多作为一个讨论贴,讨论怎么重构这样一类项目,改善开发体验,提高开发效率。

为什么需要重构?

有句玩笑话叫“重构一时爽,....”,后面就不接了。实践中,尤其对业务线的前端同学,重构整个项目风险很大,可能也没有足够时间来设计规划和执行整个重构。

但是,要不要重构,其实是个权衡利弊的过程,当弊端真的很大时,下定决心重构是一条可选的路。

对我接手的项目而言:

  1. 首先项目以PHP模板为核心(可以理解为组织前端代码的核心/入口),JS/HTML/CSS散落不同文件夹,前后端耦合,开发体验极差。

    当项目很简单时,后端模板的开发方式其实没什么可吐槽。但当项目足够复杂时,前后端耦合,相互依赖,甚至前端无法本地预览/测试功能(依赖公司内部PHP框架),那就简直是前端的噩梦。

    同时,虽然看起来是遵循所谓结构、表现和行为分离的原则,JS/HTML/CSS放置在各自独立的文件夹,但当你添加一个功能时,需要查找和修改(不止)3处地方,开发体验真的不是很好。而组件化,模块化才是正确的道路(资源内聚/内敛更利于维护)。

  2. 前端以jQuery为主的技术栈。jQuery不是问题,但在大型项目里,数据驱动,专注数据(业务逻辑)是更好的方式。

    DOM操作是必须的,但当你打开一个js文件,一大堆的$dom.on('xxx', handler),你肯定是崩溃的。尤其后面维护的同学要理清里面的逻辑不是那么容易的。

    同时项目中全局对象滥用,或者说依赖不清晰现象严重。一个JS中突然出现的全局变量你可能根本不知道它是怎么出现的,因为JS都是通过script标签引入的,你不知道哪个JS突然暴露了全局变量。

  3. CSS的问题。CSS的重复和全局冲突比较多。

  4. 冗余/废弃却未清理的代码等等。

总的来说,这个项目就像是个黑盒,不论是添加功能还是维护,都是比较痛苦。

技术选择

其实现有的React/Vue/Angular都没问题,但考虑到其他同学对框架的熟悉问题,学习曲线等等,最终选择了Vue.js。

题外话,React/Vue/Angular 三大框架互相学习进步,整体上没有大的短板了,选择哪个都可以。其中,React以JS为核心,JSX格外强大且不影响UI的声明式表达。Vue追求平衡中庸,追求符合规范,但是模板语法有时用得并不顺手(虽然可以借助工具用JSX来写)。

重构设计和规划

步子太大容易扯着蛋,本次重构的第一原则是逐步进行,最大化利用原有代码/工具等等,首先解除原有开发的最大痛点,以改善开发体验为主。

  1. 新页面用Vue实现,旧页面在迭代中逐渐改用Vue,新旧页面相互跳转;暂时不使用vue-router,保留后端路由。

  2. 暂时保留后端模板,但禁止使用include或者fis的inline指令,同时注入的数据集中在一处,通过js挂载到全局对象,尽量不使用php模板语法:

    <!DOCTYPE html>
    <html lang="zh-cn-hans">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>title</title>
      ---
      css
      ---
      <script>
      window.DATA = {
        // data here
      }
      </script>
    </head>
    <body>
      <div id="app"></div>
      ---
      script
      ---
    </body>
    </html>
  3. 添加与front同级的目录vue-front,新代码都放在这里。这里的结构可以参考vue-cli给出的样例代码。开发时mock数据window.DATA即可(开发完全脱离PHP),编译时输出静态资源(JS/CSS),资源上传到CDN,输出map文件合并到application相应文件。同时,vue-front/pages文件夹里编写相应的后端模板,编译时直接拷贝到application/views

  4. 首先产出重要公共组件:Header(Logo+头部主菜单+用户管理),Menu(左侧子菜单),Footer(版权/帮助/数据统计等),Container(内容容器,处理尺寸自适应等等)。

  5. CSS/JS的问题。

    • 原则上完全丢弃原CSS(一个大压缩文件,各种规则重复,语义不明的类名...),使用less,公共样式只使用normalize.css+一个主题定义文件(色彩/字体等)。各业务使用vue的scoped less。
    • JS的公共库包括Vue/Vuex/axios/echarts等等,各业务按需引入(不重新打包,直接模板中通过script标签引入,开发时使用webpack的alias等)。
    • 考虑引入vue-elements@2.x
  6. 数据处理的问题。

    • 使用Vuex管理状态。
    • 使用axios库,封装公共的API请求方法,方便数据统计/统一的参数封装/统一的错误处理/Mock等等。

待补充/改正

重构实践

watsy0007 commented 6 years ago

mark

qingmingsang commented 6 years ago

我还在想携程怎么会有php项目,原来你到百度去了

creeperyang commented 6 years ago

@qingmingsang 对的

For-me commented 6 years ago

我还在想百度怎么用fis,原来fis是百度的 (斜眼笑

xtx1130 commented 6 years ago

fis部署otp和agile编译准备怎么改?vue这块打包用的vue-loader还是vueify?我们这边也在改...

creeperyang commented 6 years ago

@xtx1130 vue-loader。 准备自定义一个webpack的plugin,编译的时候做打包上传cdn。

IEfucker commented 6 years ago

这种方式还能照顾爬虫吗,用vue渲染,PHP模板还有用吗

CracKerMe commented 5 years ago

对于SEO有依赖的 如何无痛考虑重构升级? 目前我选择的大刀阔斧的 vue ssr重构,空余时间去开发站内已有的各个组件,但是好像老板不大愿意接受重构,我作为小负责人 该如何考虑?

creeperyang commented 5 years ago

对于SEO有依赖的 如何无痛考虑重构升级? 目前我选择的大刀阔斧的 vue ssr重构,空余时间去开发站内已有的各个组件,但是好像老板不大愿意接受重构,我作为小负责人 该如何考虑?

既然大刀阔斧了,可以考虑引入node做中台,直接支持 vue-ssr 一步到位,后面好处更多。

如果不愿意一步跨步这么大,可以考虑对页面在部署或者预热过程中生成对应静态页面,来优化 SEO。

xtx1130 commented 5 years ago

@creeperyang 你们在做node中台吗?目前我们用nginx做的路由分发打到ssr,准备中间加一层nodejs,由nodejs对接下游的ssr和其他平台。但是我怕性能影响太大。一直在犹豫。

creeperyang commented 5 years ago

nginx+node中台

xtx1130 commented 5 years ago

@creeperyang 和单纯的nginx相比,性能损耗大概在多少百分比