You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7如何配置实现React所用JSX文件的编译?

Rails 7 环境下实现React组件调用的落地方法

Rails 7 默认替换掉了旧的Webpacker,默认用Importmap做JS模块管理,也提供了jsbundling-rails对接esbuild/rollup等打包工具,你之前用的react-rails gem完全兼容Rails 7,按下面步骤配置就能实现你要的调用效果,和你之前的开发习惯差别很小。

推荐方案:react-rails + esbuild(适配原有开发习惯)

  • 安装基础依赖
    先在Gemfile里添加两个gem:
    gem "react-rails"
    gem "jsbundling-rails"
    
    执行bundle install完成gem安装,接着跑esbuild安装命令:rails javascript:install:esbuild,这一步会自动帮你配置好JS打包的输出路径、布局文件的JS引用标签。
    之后装React相关的npm依赖:
    yarn add react react-dom @babel/preset-react
    # 用npm的话就跑 npm i react react-dom @babel/preset-react
    
    最后跑react-rails的安装生成器:rails g react:install,命令执行完会自动在app/javascript下创建components目录,你把现有的star_rating.js.jsx文件直接放进这个目录就行,记得给组件加默认导出,举个正确的组件写法示例:
    // app/javascript/components/star_rating.js.jsx
    import React from 'react'
    export default function StarRating({ name, value, onStarClick }) {
      // 你自己的组件逻辑,比如星星渲染、点击事件处理
      return <div className="star-rating">{/* 业务逻辑 */}</div>
    }
    
  • 调整esbuild配置支持JSX解析
    打开根目录下的esbuild.config.js,修改打包配置,添加JSX后缀支持和路径别名,省得每次引入组件都写长串相对路径:
    const path = require('path')
    require("esbuild").build({
      entryPoints: ["application.js"],
      bundle: true,
      outdir: path.join(process.cwd(), "app/assets/builds"),
      absWorkingDir: path.join(process.cwd(), "app/javascript"),
      loader: {
        '.js': 'jsx',
        '.jsx': 'jsx'
      },
      resolveExtensions: ['.js', '.jsx'],
      // 原有sourcemap等配置保留即可
    }).catch(() => process.exit(1))
    
    接着修改app/javascript/application.js,把React、ReactDOM和你要全局用的组件挂到window对象上,这样其他任意JS代码都能直接调用:
    import React from 'react'
    import ReactDOM from 'react-dom/client'
    import StarRating from 'components/star_rating'
    
    window.React = React
    window.ReactDOM = ReactDOM
    window.StarRating = StarRating
    
    要是你用的是React 17及以下版本,react-dom的引入和render方法保持你原来的写法就行,不用改createRoot。
  • 验证调用逻辑
    配置完跑rails assets:precompile或者直接启动bin/dev(会自动监听JS文件变化热重载),你在任意JS代码里直接写你需要的调用逻辑就可以:
    let starRating = <StarRating name={name} value={initialValue} onStarClick={onClick} />;
    // React 18 写法
    ReactDOM.createRoot(someContainerElem).render(starRating)
    // React 17及以下用原有写法即可:ReactDOM.render(starRating, someContainerElem)
    
    注意Rails 7默认开启Turbo,不要在DOM没加载完成的时候就去拿容器节点,最好把渲染逻辑绑在Turbo的加载事件里,避免找不到节点报错:
    document.addEventListener('turbo:load', () => {
      const container = document.querySelector('#star-rating-wrap')
      if (!container) return
      // 从dataset拿初始化参数的逻辑
      const { name, initialValue } = container.dataset
      const onClick = (val) => console.log('用户评分:', val)
      const starRating = <StarRating name={name} value={Number(initialValue)} onStarClick={onClick} />
      ReactDOM.createRoot(container).render(starRating)
    })
    

轻量备选:纯Importmap方案(不用打包工具)

如果你的React组件不多,不想引入打包流程,也可以直接用Rails 7默认的Importmap实现:

  • 执行bin/importmap pin react react-dom把React相关依赖固定到importmap
  • 再执行bin/importmap pin @babel/standalone引入babel转译器用来处理JSX语法
  • 这种方案不需要提前打包,但是写JSX的script标签要加type="text/babel"属性,适合小型项目用,组件多的话转译性能不如提前打包的esbuild方案,优先选第一种就行。

内容的提问来源于stack exchange,提问作者Some Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:48:32