はじめに
Rails + Vue.js + TypeScriptで趣味プログラミングしてみようと思って開発環境を構築していたら思いの外ハマったので備忘録として残しておきます。
RailsやWebpackerのバージョンが変わったら設定もまた変わりそうなので(Webpacker3.0系と3.2系でもconfigファイルの書き方が微妙に違うようでした)、以下のバージョンにおいて動作確認しているということをお見知りおきください。
環境
- Ruby 2.5.0
- Rails 5.1.4
- Webpacker 3.2.1
プロジェクトを作成してVue.jsが動くようにする
まずはrailsプロジェクトを作ります。今回はオプション無しでやります。
$ rails new sample
エディタでGemfileを開きwebpacker gemを追記した上で bundle install
します。成功したら webpacker:install
しましょう。
$ emacs Gemfile
# webpackerを追記
gem 'webpacker', '~> 3.0'
$ bundle
# bundle installできたらwebpackerをインストール
$ bundle exec rails webpacker:install
問題なければそのままwebpackerでVue.jsをインストールします。
$ bundle exec rails webpacker:install:vue
インストールがうまくいったら、Vue.jsの動作確認のためcontroller、view、routesに以下のように追記(もしくは新規追加)します。
class HomeController < ApplicationController
def index
end
end
<%= stylesheet_pack_tag 'hello_vue' %>
<%= javascript_pack_tag 'hello_vue' %>
Rails.application.routes.draw do
root to: 'home#index'
end
サーバを立ち上げて確認してみます。
$ bundle exec rails s
ここで bin/webpack-dev-server
も立ち上げてみようとするとエラーになるので、エラー文に書いてあるとおり実行します。
# エラーになる
$ bin/webpack-dev-server
Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.
# エラーに書いてあるとおり実行
$ bundle binstubs bundler --force
# 今度はOK
$ bin/webpack-dev-server
10% building modules 2/2 modules 0 active
Project is running at http://localhost:3035/
webpack output is served from /packs/
(中略)
webpack: Compiled successfully.
TypeScriptのインストールと設定
Vue.jsは動くようになったので今度はwebpackerでTypeScriptをインストールします。
$ bundle exec rails webpacker:install:typescript
TypeScriptが使えるようになったはずなので以下の二箇所に変更を加えてみましょう。
- Rename:
app/javascript/packs/hello_vue.js
->app/javascript/packs/hello_vue.ts
-
app/javascript/app.vue
のscript部分にTypeScriptを指定
</div>
</template>
-<script>
+<script lang="ts">
export default {
data: function () {
return {
これで bin/webpack-dev-server
を動かしてみますが、次のようなエラーが出ると思います。
$ bin/webpack-dev-server
(中略)
Failed to compile.
./app/javascript/packs/hello_vue.ts
[tsl] ERROR in /path/to/project/app/javascript/packs/hello_vue.ts(9,17)
TS2307: Cannot find module '../app.vue'.
これはTypeScriptから .vue
ファイルが読めていないということなので ./config/webpack/loaders/typescript.js
を以下のように編集します。
module.exports = {
test: /\.(ts|tsx)?(\.erb)?$/,
use: [{
- loader: 'ts-loader'
+ loader: 'ts-loader',
+ options: {
+ appendTsSuffixTo: [/\.vue$/]
+ }
}]
}
bin/webpack-dev-server
を動かしてCompiled successfullyすればOKです。
$ bin/webpack-dev-server
(中略)
webpack: Compiled successfully.
Vue.jsの型定義ファイルの追加
今までの流れでRails + Vue.js + TypeScriptの設定はOKだと思ったのですが、適当にコンポーネントファイルでも追加するかと app/javascript/packs/components/header.vue
のようなファイルを作成して hello_vue.ts
でインポートしてみたところ
<template>
<p>custom header</p>
</template>
import Vue from 'vue'
import App from '../app.vue'
+import Header from './components/header.vue'
document.addEventListener('DOMContentLoaded', () => {
const el = document.body.appendChild(document.createElement('hello'))
また Cannot find module のエラーが出ました。
$ bin/webpack-dev-server
(中略)
ERROR in ./app/javascript/packs/hello_vue.ts
[tsl] ERROR in /path/to/project/app/javascript/packs/hello_vue.ts(10,20)
TS2307: Cannot find module './components/header.vue'.
この問題を解決するにはどうもVue.jsの型定義ファイルが必要とのことだったので app/javascript/types/vue.d.ts
あたりに以下のような内容のファイルを追加します。
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
これで動くようになったはずです。
$ bin/webpack-dev-server
(中略)
webpack: Compiled successfully.
おわりに
というわけでRails + Vue.js + TypeScriptで開発できるようになりました、多分。
ただ、何故App.vueは型定義ファイルがなくてもhello_vue.tsから読み込めるのか…これが分からない
誰かご教授いただけると幸いです
Reference
- https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11
- https://qiita.com/maeharin/items/99eb03e1fe8ab89f4e4d
- https://qiita.com/YukiYonekura/items/a5b3905fb05b395531af
- https://github.com/rails/webpacker/blob/master/docs/typescript.md
- https://tisnote.com/rails-webpacker-react-typescript/
- https://jp.vuejs.org/v2/guide/typescript.html