Rails 7は輸入マップを脚光に出す


Rails 7はJavaScript生態系にパラダイムシフトをもたらしている.我々がRailsが好きである理由の1つは、DEVSが現状に挑戦するために大きな変化をするのを恐れていないので、理由です.Import Maps Rails 7が新しくなった何か新しいものではありません.しかし、それは現在のJavascript生態系である混乱を逃れるためにプッシュを必要とする何かです.
次世代のJavaScriptを書きたいです.そしてそうすることで私たちは様々なビルドツールを学び、使用するようになります.多くのブラウザは既にECMAScript仕様の様々な新機能をサポートし始めました.ES Modules 彼らの1人であること.

ブラウザ内のESモジュールの現在の状態


The browsers that support ES Modules 経由で<script> タグは3つの方法で行います.
  • 相対パス(現在のファイルに対する相対パス)を使用します.
  •   import foo, { bar } from "../../foobar.js";
    
  • または絶対パス( Webrootに対して)を使用します.
  •   import foo, { bar } from "/baz/foobar.js";
    
  • またはURLを使用する
  •   import foo, { bar } from "https://example.com/baz/foobar.js";
    
    ご覧のように、これはインポートがどのようにノードで働くかとは異なります.ノードでは、NPMパッケージの名前を指定できます.
    import foo, { bar } from "foobar";
    
    とノードは、node_modules フォルダ.ブラウザで裸のモジュール指定子を使ってモジュールを参照するのと同じ結果を得るには、インポートマップが必要です.

    どのようにインポートマップが動作しますか?


    名前としてインポートマップは、“インポート”のための“マッピング”です.彼らは、私たちが裸のモジュール指定子を使ってものを輸入するのを許します.マッピング情報は、ブラウザを介して<script> タグ付きtype="importmap" :
    <script type="importmap">
      {
        "imports": {
          "foobar": "/baz/foobar.js"
        }
      }
    </script>
    

    インポートマップができる他の何かがありますか?


    はい.以下はインポートマップの機能の一部ですが、これらに限定されません.機能の完全なリストについては、を読むofficial spec .

    プレフィックス


    一致するように正確なものを指定する代わりに、フォルダ接頭辞を指定することができます(フォワードスラッシュで終了).
    {
      "imports": {
        "foobar/": "/baz/foobar/"
      }
    }
    
    を参照してください/baz/foobar フォルダを指定します
    import foo from "foobar/foo.js";
    import bar from "foobar/bar.js";
    

    指紋


    ファイル指紋を使用すると、ブラウザが名前に基づいてファイルを無効にすることができます.
    import foo, { bar } "/baz/foobar-46d0g2.js";
    
    しかし、フィンガープリントされた輸入をすることは、私たちのために2つの問題を引き起こします:
  • 私たちは、ファイルのときに指紋を変更する気になるビルドシステムを持っている必要があります/baz/foobar.js 変化
  • そして、ファイルの指紋に応じてfoobar.js 同様に更新する必要があります.つまり、ブラウザは現在、両方のファイルをダウンロードする必要がありますfoobar.js 変更.より多くのファイルがfoobar.js .
  • インポートマップを使用すると、指紋ファイルを非指紋に再マップできます.
    {
      "imports": {
        "/foobar.js": "/foobar-8ebg59.js"
      }
    }
    
    これで、インポートマップを更新するだけで、ブラウザに余分なコストはかかりません.

    フォールバック


    インポートマップを使用すると、複数のマッピングを指定できます.
    {
      "imports": {
        "foobar": [
          "https://example.com/baz/foobar.js",
          "/baz/foobar.js"
        ]
      }
    }
    
    ブラウザを指示するだけでダウンロードする/baz/foobar.js 私たちのサーバーからhttps://example.com (何らかの理由でドメインブロッキングなど).

    スコープ


    パッケージが別のパッケージのバージョンを予想する依存関係の問題があるとしましょう.
    {
      "imports": {
        "foobar": "/baz/foobar-v2.js",
        "barfoo": "/baz/barfoo.js"
      }
    }
    
    上記のシナリオでは/baz/barfoo.js 依存する/baz/foobar-v1.js の代わりに/baz/foobar-v2.js 指定した通りです.このジレンマを解決するために、別の兄弟キーを"imports" キー"scopes" :
    {
      "imports": {
        "...": "..."
      },
      "scopes": {
        "/baz/barfoo.js": {
          "foobar": "/baz/foobar-v1.js"
        }
      }
    }
    
    ファイル内のブラウザに指示する/baz/barfoo.js , "foobar" 解決すべき"/baz/foobar-v1.js" 代わりに.

    どのように、レールは絵に入りますか?


    手でこの輸入マップを書くことは、退屈なプロセスであるかもしれません.Railsは設定ファイルを提供しますconfig/importmap.rb ) あなたは非常に簡単にインポートマップを生成することができます経由.
    内部config/importmap.rb , 二つの方法にアクセスできます.
  • pin(name, to: nil, preload: false)
  • pin_all_from(dir, under: nil, to: nil, preload: false)
  • pin を指定すると、:to オプションを指定します.
    pin "foobar", to: "/baz/foobar.js"
    
    これは、裸のモジュール指定子"foobar" アセットパイプライン変換ファイル"/baz/foobar.js" :
    {
      "imports": {
        "foobar": "/assets/baz/foobar-i0f472.js"
      }
    }
    
    Without the :to オプション(資産パイプラインのファイルを参照)
    pin "foobar"
    
    pin はファイル名(.js ) 最初の引数自体から
    {
      "imports": {
        "foobar": "/assets/foobar-mt22u90.js"
      }
    }
    
    このアプローチの美しさは、インポートマップは、複雑なビルドプロセスを持つことなく、レールの資産パイプラインとうまく統合されています.pin_all_from は、フォルダの下にファイルのツリー全体をマップすることができます:under オプション):
    pin_all_from "app/javascript/foobar", under: "foobar"
    
    書くことから私たちを救うpin すべてのファイルについての文
    {
      "imports": {
        "foobar/foo": "/assets/foobar/foo-v8th63e.js",
        "foobar/bar": "/assets/foobar/bar-wi93v01.js"
      }
    }
    
    提供するファイルはfoo.js and bar.js インサイドapp/javascript/foobar フォルダ.また、ある場合index.js ファイルと並んでfoo.js and bar.js , そして、:under :
    {
      "imports": {
        "foobar/foo": "/assets/foobar/foo-e113b5.js",
        "foobar/bar": "/assets/foobar/bar-5b3d33.js",
        "foobar": "/assets/foobar/index-f70189.js"
      }
    }
    
    私たちも完全に別の名前の下にフォルダ内のファイルをマップすることができますが、警告は:to オプションを指定します.
    pin_all_from "app/javascript/foobar", under: "barfoo", to: "foobar"
    
    柵が内部のフォルダを把握するのを助けますpublic/assets からの処理ファイルapp/javascript/foobar が置かれます:
    {
      "imports": {
        "barfoo/foo": "/assets/foobar/foo-e113b5.js",
        "barfoo/bar": "/assets/foobar/bar-5b3d33.js",
        "barfoo": "/assets/foobar/index-f70189.js"
      }
    }
    
    入れ子になったフォルダ内のすべてのファイルをピンで囲むこともできます.
    pin_all_from "app/javascript/foobar/barfoo", under: "foobar/barfoo"
    
    ネストしたフォルダの中のツリー全体をマップするbarfoo/ 現在foobar/ :
    {
      "imports": {
        "foobar/barfoo/bar": "/assets/foobar/barfoo/bar-e07c61.js",
        "foobar/barfoo/baz": "/assets/foobar/barfoo/baz-7079be.js",
        "foobar/barfoo": "/assets/foobar/barfoo/index-83fecf.js"
      }
    }
    
    または、入れ子になったフォルダを別の名前でピンに入れたい場合は
    pin_all_from "app/javascript/foobar/barfoo", under: "barfoo/foobar", to: "foobar/barfoo"
    
    ネストしたフォルダ内のツリー全体をマップするbarfoo/ 現在foobar/ :
    {
      "imports": {
        "barfoo/foobar/bar": "/assets/foobar/barfoo/bar-07689a.js",
        "barfoo/foobar/baz": "/assets/foobar/barfoo/baz-486f9d.js",
        "barfoo/foobar": "/assets/foobar/barfoo/index-e9a30c.js"
      }
    }
    
    しかし、異なる裸のモジュール指定子の下で.
    ジャスト・コールpin or pin_all_from 内部メソッドconfig/importmap.rb 十分ではない.電話をかける必要があるjavascript_importmap_tags 内部ヘルパーメソッドを表示<head> 我々の意見のタグ
    <head>
      <%= javascript_importmap_tags %>
    </head>
    
    これは実際に参照するブラウザの生成されたインポートマップを挿入します.
    両方pin and pin_all_from オプション引数を受け取ります:preload , そのときtrue<link> タグ付きrel="modulepreload" インポートマップの配置前
    <head>
      <link rel="modulepreload" href="/assets/baz/foobar.js">
    
      <script type="importmap">
        {
          "imports": {
            "...": "..."
          }
        }
      </script>
    </head>
    
    これにより、ブラウザがアイドル時間を使用して他のモジュールがインポートする前にファイルをダウンロードすることができます.

    免責事項


    このブログを書く時に、Rails 7はまだ完全にリリースされません.それで、インポートマップに関して多くのパブリックAPIが変わるかもしれません.それで、それらの変化のために目を離さないでください.

    参考文献

  • WICG / import-maps
  • Import maps - HTTP 203
  • rails / importmap-rails
  • Alpha preview: Modern JavaScript in Rails 7 without Webpack