JavaScript Rails 项目里使用 React 的方式

qichunren · 2022年05月09日 · 最后由 jisuanjixue 回复于 2022年10月15日 · 1098 次阅读

我自己其实也在折腾前端,感觉还是没有真正找到一个合适的方案。前端这玩意,感觉折腾进来了,就无止境了,所以在选型一个技术框架的时候得全面考查清楚。我记得很久以前出来了 AngularJS,我研究了一阵子,感觉很惊艳,在一个项目中采用了,后面你看,出来了 Angular2,完全不兼容了,再后面出来 React / Vue 这些,基本没有人搞 AngularJS 了。所以对前端技术的选型应该是一个很慎重的问题。

我目前自己做一个电商网站,我采用的是 Rails 7 / esbuild / Turbo / Stimulus, 对于大部分的数据展示页面和表单都是采用 Rails 原生的那一套很直观地快速实现,但是有些复杂一点的页面,如商品图片管理,包括图片即时批量上传、排序、简单编辑等,用 React 的最基本库 + Json + ActiveStorageDirectUpload 就解决问题了,可以说复杂度减少数倍。

我目前使用 React 的方法是通过 Stimulus Controller 集成 React 的。这样的话,在某些特定页面里局部使用 React 简化一些交互。

import { Controller } from "@hotwired/stimulus"
import * as React from 'react'
import * as ReactDOM from "react-dom";
import ProductMedia from "../components/product_media"

export default class extends Controller {
  connect() {
    let product_id = this.element.dataset.product_id;
    let url = this.element.dataset.directUploadUrl;    
    ReactDOM.render(<ProductMedia product_id={product_id} upload_url={url} />, this.element);
  }
}

其实我好想找到一个合适好用的 Rails 前端集成方案,同时又能不失去 Rails 的特性的途径。我了解的各种可能的方法有(不限于):

  1. React 纯前端 (Create React App) + Rails JSON API, 前后端项目分离
  2. NextJS + NodeJS + Rails JSON API 前后端项目分离
  3. react_on_rails
  4. 我上面提到的通过 Stimulus 集成,选择性的在某一些页面里采用 React app
  5. lit

我想请教一下大家,你们的真实项目里是怎么样使用 React 这类的框架呢?有没有什么实践分享一下,谢谢。

说到 React,刚好前几天看到有一个 v2ex 上的帖子 2022 年 react 生态,大家都用啥 看看有多少名词吧?

从人力资源的角度看,

如果公司 ruby 人员长期充足且都是全栈的能手,那么集成在 rails 里效率应该是很高的。

但在快速拓展业务的时候想招个 ruby 都难,而且还要求全栈能手时,想想有多难呢,而且公司的目标也不是为了一定用什么技术语言吧。

方案 1 是我们项目正在推进的方向。

方案 2 我们的一个官网当时为了 SEO 和 SSR 选择的,效果不理想,前端也很少有人专门研究 NextJS,不通用。

方案 4 和你的类似,我们从 rails 5 就有个在 rails 里写 react 的,但对 ruby 后端来说太难上手了,一般人维护不了,正在招人改成方案 1。

所以,我更倾向于选择【1.React 纯前端 (Create React App) + Rails JSON API, 前后端项目分离】

前端的人招相对好找;再有 ruby 后端不够,其他后端来凑嘛。

个人也比较建议前后端分离。😂 折腾自己的项目无所谓。公司的需求压过来的时候着实很难

  1. 交互体验
  2. 后台逻辑
  3. 样式

同时把这些都扛在自己身上。到最后只会筋疲力尽。干脆分离算了,把交互体验跟样式让喜欢做这些的小伙伴来接收,自己可以更专心写 Ruby。

毕竟 Ruby 已经很难招了,如果要再招一个既能写 Ruby 又愿意写交互的人来接手前后端不分离的项目,估计更难找到合适的人。

PS:公司前期就是 ActiveAdmin 来堆后台逻辑,但是后台这东西要开发得好,需要花费的精力不亚于开发一个 to C 的产品。所以我们后来决定用 React 来进行重写,我只负责提供 API,交互样式各种逻辑都让熟悉前端的小伙伴来做。这样后端工程师的担子也会少一些。

我在用 VUE 做全栈,使用的 Webpacker。没用 rails7 那一套前端方案,那一套太另类了,前端界现成的轮子很多都用不起来,成本太高。

我这里系统,因为有角色系统的的需求,所以不想使用 2 套路由,配置起来太麻烦了。所以拒绝前后端分离。

vue 文件放到 Rails 的 views 目录下了,不在 packs 写 js component 太割裂。放在一起十分舒服。这套整成 react 的话应该区别不大。

application.js 里只有这些,自动加载到 rails 的 views 目录下。

import '../stylesheets/application';
// import 'bootstrap-vue/dist/bootstrap-vue.css'
require('admin-lte');
window.bootstrap  = require('bootstrap');
window.bootbox    = require('bootbox');

import "@fortawesome/fontawesome-free/js/all";

import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import 'vue-area-linkage/dist/index.css';
import VueAreaLinkage from 'vue-area-linkage';
import BaiduMap from 'vue-baidu-map'
import _ from 'lodash'
import dayjs from 'dayjs'
import VueSweetalert2 from 'vue-sweetalert2';
import 'sweetalert2/dist/sweetalert2.min.css';
import VueTreeList from './component/vue-tree-list/index.js'



Vue.prototype._ = _ 
Vue.prototype.dayjs = dayjs 
Vue.use(VueAreaLinkage)
Vue.use(BaiduMap, {
  // ak 是在百度地图开发者平台申请的密钥 详见 http://lbsyun.baidu.com/apiconsole/key */
  ak: '========='
})
Vue.use(VueSweetalert2);
Vue.use(VueTreeList);




Rails.start()
Turbolinks.start()
// Turbolinks.setProgressBarDelay(1000);
ActiveStorage.start()

document.addEventListener('turbolinks:load', () => { 
  const element_path = $('body').data('element-path')
  const app = new Vue({
    el: '#app' ,
    components: {
      'vue-component' : () => import('../../views/' + element_path + '.vue')
    }
  })
})

我这现在主要是专注业务,所以技术方案没整理。前端样式框架用的 Adminlte,基于 bootstrap 的,所以 jquery 还在。

大一统的前端框架真的很恶心,想拆什么整合什么,还是需要大量人力物力。我就用这种自己拼的。需要什么组件,就去拆几个进来。现在拼了百度地图、无限分类树、省市地三级级联,都没什么问题。

react 的方案你可以琢磨一下。

Nextjs 如果只是使用的话,基本无感吧,最大的区别就是不能随便直接在文件里面访问浏览器的 API 了,必须在页面渲染了之后才能调用,比如在 useEffect(() => {}, []) 里面,很多事情 Next 都帮我们做了

前后端分离的方案在目前这个阶段我个人是真的不认同的,把所有的前端工程架在一个看起来不是那么面向未来的技术框架之上,我是不放心的。我觉得浏览器原生的技术标准才是未来。

从技术上看,顶楼的方法没问题。stimulus 负责绑定服务端渲染的组件,react 负责客户端视图渲染和行为,他们是互补的关系。lit 综合了两者的优点,似乎是更好的选择,我未来也打算试用 lit。

从管理上看,选择的技术要符合团队的技术栈,只要团队都能接受就行。现实上全栈的人难招,市场上前端几乎代表着前后端分离了,如果业务需要团队在一年内扩展 100 人,那么只能适应现状走分离路线。但对于小公司,未来一年最大问题是是否存活,开发人员只有几个人,每个人什么都干,那么全栈是比较好的选择。

qichunren 回复

用原生 DOM 手写也能前后端分离呀,分离也不依靠框架。框架提供的只是声明式视图能力而已。

Rei 回复

lit 搭配 rails 有案例推荐吗?

v2up 回复

我也刚开始学,看上去就像 stimulus + react,而且是基于 web component。

富前端就用 Rails API 模式

我最近也在折腾怎样集成 react,一般大部分交互逻辑(如简单的增删改查,用 Rails 7 + esbuild + Turbo + Tailwindcss),但是有些复杂的前端交互和业务逻辑就头疼,用 React 现有的轮子就好处理一些。另外感觉没有 JS 的纯的 Tailwindcss UI 组件现在也有好些,可以直接拿来用,可以少写很多 css 😀

最近在学习时看到一种集成 React 的方法进行表单交互操作,用 document.addEventListener() , ReactDOM.createRoot(), fetch(), turbo_stream, Turbo.renderStreamMessage, 直接上代码仓库https://github.com/mixandgo/hotwire_react

这种纯前端的解决方案,项目如果有 SEO 方面的考量,就比较费劲,试了 react 的 prerender, 毛病实在太多了。

可以考虑用https://github.com/inertiajs/inertia-rails 和 inertiajs 方案,直接在 rails 的 controllers 里 render data 到相应的前端框架 components 上,inertiajs 定义为 Build single-page apps, without building an API.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号