Madogiwa Blog

主に技術系の学習メモに使っていきます。

Rails 7から導入される予定のimportmap-railsを使ったフロントエンド環境を試してみる

Rails 7からimportmap-railsを使ったフロントエンド環境が提供される予定です。

Rails new時にimportmap-railsを使用するoptionも追加され試しやすかったので、軽く使ってみました。

利用方法とかメモしておきます📝

github.com

github.com

import mapsとは

簡単にいうと以下のような定義を元に、

<script type="importmap">
{
  "imports": {
    "moment": "/node_modules/moment/src/moment.js",
    "lodash": "/node_modules/lodash-es/lodash.js"
  }
}
</script>

以下のようにimportを表現出来る機能なようです。

import moment from "moment";
import { partition } from "lodash";

詳細な説明は以下を参照してください🙇‍♂️

github.com

これによりwebpackのようなbuildツールを使わなくてもimportを利用することが出来るのと、HTTP/2により並列で取得出来るファイル数に制限がなくなった。IE11のEOLも迫りES6が動かないブラウザはほとんど無いということで、importmapを利用した環境を採用し、Railsからnodeの依存を外そうということでimportmap-railsを使ったフロントエンド環境が候補に上がったようです(?)

world.hey.com

importmap-railsを使ってRailsでimportmapでフロントエンド環境を構築してみる。

今回は簡単なReactのコンポーネントimport mapsを使ってレンダリング出来るとことまでをやってみようと思います。

importmap-railsを使うにはrailsmainブランチからinstall後に以下のコマンドを実行することでimportmap-railsを導入した状態でRails newを行う事ができます🚃

$ rails new --javascript=importmap

Rails newしたあとに以下のコマンドを実行しimportmap-railsのセットアップを行います。

bin/rails importmap:install
Add Importmap include tags in application layout
      insert  app/views/layouts/application.html.erb
Create application.js module as entrypoint
      create  app/javascript/application.js
Ensure JavaScript files are in the asset pipeline manifest
      append  app/assets/config/manifest.js
Configure importmap paths in config/importmap.rb
      create  config/importmap.rb
Copying binstub
      create  bin/importmap

importmap-railsは現状assets:precompileでbuildしたjsを読み込むような挙動になっているようです👀

github.com

install後にbin/importmap pin nameを使ってライブラリのCDNのURLを登録します。

$ bin/importmap pin react-dom
Pinning "react-dom" to https://ga.jspm.io/npm:react-dom@17.0.2/index.js
Pinning "object-assign" to https://ga.jspm.io/npm:object-assign@4.1.1/index.js
Pinning "react" to https://ga.jspm.io/npm:react@17.0.2/index.js
Pinning "scheduler" to https://ga.jspm.io/npm:scheduler@0.20.2/index.js

このときのライブラリの名前とCDNのURLの解決は以下が利用されているようです👀

jspm.org

github.com

実際に登録されているライブラリはconfig/importmap.rbで見ることが出来ます📦

pin "application"
pin "react", to: "https://ga.jspm.io/npm:react@17.0.2/index.js"
pin "object-assign", to: "https://ga.jspm.io/npm:object-assign@4.1.1/index.js"
pin "react-dom", to: "https://ga.jspm.io/npm:react-dom@17.0.2/index.js"
pin "scheduler", to: "https://ga.jspm.io/npm:scheduler@0.20.2/index.js"

これらの登録したライブラリはjavascript_importmap_tagsで読み込まれます。

<!DOCTYPE html>
<html>
  <head>
    <title>SampleApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

これでライブラリを登録できたので適当なページを用意してapplicaton.jsにReactのコードを記載してみます。

<h1>TOP</h1>

<div id="root">
</div>
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails

console.log("application.js");

import ReactDOM from "react-dom";

ReactDOM.render("Hello, world!", document.getElementById("root"));

以下の通りimport-maps利用したインポートが行われ

<script type="importmap" data-turbo-track="reload">{
  "imports": {
    "application": "/assets/application-e92f8138755b2135e2a621bfbb917dc7f07214686408cf58ca18cf919cf1cc72.js",
    "react": "https://ga.jspm.io/npm:react@17.0.2/index.js",
    "object-assign": "https://ga.jspm.io/npm:object-assign@4.1.1/index.js",
    "react-dom": "https://ga.jspm.io/npm:react-dom@17.0.2/index.js",
    "scheduler": "https://ga.jspm.io/npm:scheduler@0.20.2/index.js"
  }
}</script>
<link rel="modulepreload" href="/assets/application-e92f8138755b2135e2a621bfbb917dc7f07214686408cf58ca18cf919cf1cc72.js">
<link rel="modulepreload" href="https://ga.jspm.io/npm:react@17.0.2/index.js">
<link rel="modulepreload" href="https://ga.jspm.io/npm:object-assign@4.1.1/index.js">
<link rel="modulepreload" href="https://ga.jspm.io/npm:react-dom@17.0.2/index.js">
<link rel="modulepreload" href="https://ga.jspm.io/npm:scheduler@0.20.2/index.js">
<script src="/assets/es-module-shims-c7d42ad90c35e70ec01698a6f481a4eacabafe8c30cae13fa50c7c0d287a1563.js" async="async" data-turbo-track="reload"></script>
<script type="module">import "application"</script>

コンポネントも表示されています🎉

f:id:madogiwa0124:20210905135456p:plain

おわりに

小規模でJSも少しだけしか使わないケースにはnodeの依存もなくせて、良いかもですね👀

参考

www.youtube.com