環境:Rails 6.0、Webpacker 4.2、Vue.js 2.6、React 16.12
Webpackerを使ってVue.jsとReactの両方を動かすことに成功したので、メモしておきます。
コピー元の作成
まず、設定ファイルのコピー元とするだけのアプリケーションを作成します。すでにVueを入れたアプリケーションがある場合は、Reactで作ります。
% rails new reactapp --webpack=react
Reactを入れたアプリケーションがある場合は、Vueを指定します。
% rails new vueapp --webpack=vue
yarn add
Vueで作ってあるアプリケーションには、Reactのモジュールをインストールします。prop-typesはWebpackerがデフォルトで入れるものですが、必須ではありません。
% yarn add @babel/preset-react babel-plugin-transform-react-remove-prop-types prop-types react react-dom
Reactで作ってある場合は、Vueのモジュールをインストールします。
% yarn add vue vue-loader vue-template-compiler vue-turbolinks
babel.config.js
ルートにあるbabel.config.jsは、Reactで生成したものを使います。つまり、すでにReactならそのままにし、VueならReact用のbabel.config.jsを上書きします。
config/webpacker.yml
config/webpacker.ymlは、元からあるものを使い、Reactを加える場合は.jsx
を、Vueを加える場合は.vue
を追加します。
extensions:
- .vue
- .jsx
config/webpacker/
ReactにVueを加える場合は、Vueで生成したものからconfig/webpacker/loaders/vue.jsをコピーします。
また、config/webpacker/environment.jsはVueのもので上書きします。
両方動かしてみる
次のような感じで両方を動かすapplication.jsを書いて動けば成功です。
require("@rails/ujs").start();
require("turbolinks").start();
import React from 'react';
import ReactDOM from 'react-dom';
import Vue from 'vue';
import TurbolinksAdapter from 'vue-turbolinks';
import VueApp from '../vueapp';
import ReactApp from '../reactapp';
Vue.use(TurbolinksAdapter);
document.addEventListener('turbolinks:load', () => {
if($('#vue-app').length) {
new Vue(VueApp).$mount('#vue-app');
}
if($('#react-app').length) {
ReactDOM.render(React.createElement(ReactApp), $('#react-app')[0]);
}
});
実際にこんなアプリケーションを作ることはないと思いますが、現実的な使い方として考えられるのは、Railsアプリケーションの中でVueを使う部分とReactを使う部分を分けるケースです。その場合は、app/javascript/packsの下にVue用とReact用のxxx.jsを作り、レイアウトテンプレートを複数作ってjavascript_pack_tagを切り替える、ということになるでしょう。