インポートマップを使用してJavaScriptを動的にインポートする方法
序章
外部ライブラリは、新しいJavaScriptプロジェクトを複雑にする可能性があります。 外部コードライブラリをインストールして使用できるようにするには、コードを解析し、インポートしたライブラリを最終的な形式にバンドルできるビルドツールが必要です。 ビルドのセットアップ後、新しいコードを簡単に追加および統合できますが、それでもいくつかの問題があります。
たとえば、管理ページのように、アプリケーションの一部、ほとんどのユーザーが必要としない可能性のあるアプリケーションの一部にライブラリが必要な場合があります。 ただし、デフォルトでは、ほとんどのビルドシステムはすべてのコードを1つの大きなファイルにバンドルします。 ユーザーは、コードを実行する必要があるかどうかに関係なく、コードをロードします。 ビルドシステムは、必要に応じてコードをロードするように構成できるほど十分な柔軟性がありますが、プロセスにはある程度の作業が必要です。
ビルドツールは開発エクスペリエンスの重要な部分ですが、 import maps と呼ばれる仕様により、ビルドツールなしで外部コードをプロジェクトにインポートでき、必要な場合にのみコードをロードできます。ランタイム。 マップのインポートは、スタイルシートの作成や画像の処理など、他の多くの価値のあるアクションを実行するビルドツールを完全に置き換えるものではありませんが、ネイティブブラウザ機能のみを使用して新しいJavaScriptアプリケーションをすばやく簡単にブートストラップできます。
このチュートリアルでは、インポートマップとJavaScriptモジュールを使用して、ビルドツールなしでコードをインポートします。 メッセージを表示する基本的なアプリケーションを作成し、外部コードの場所をブラウザーに通知するインポートマップを作成します。 次に、インポートしたコードをJavaScriptに統合し、コードをローカルにダウンロードしたり、ビルドステップを実行したりすることなく、サードパーティのコードを使用します。 最後に、インポートマップの多くの側面を実装し、最新のすべてのブラウザで動作する現在のツールについて学習します。
前提条件
-
Node.jsを実行する開発環境が必要になります。 このチュートリアルは、Node.jsバージョン14.17.1およびnpmバージョン6.14.23でテストされました。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはの
PPAを使用したインストール ]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。 -
また、 JavaScriptのコーディング方法にあるJavaScriptの基本的な知識と、HTMLおよびCSSの基本的な知識も必要です。 HTMLとCSSの優れたリソースは、 Mozilla DeveloperNetworkです。
ステップ1—HTMLページの作成とJavaScriptの挿入
このステップでは、HTMLページを作成し、動的なアクティビティにJavaScriptを使用し、ローカル開発サーバーを起動して変更を追跡します。
まず、新しいディレクトリで、空白のHTMLドキュメントを作成します。
というファイルを開きます index.html
テキストエディタの場合:
- nano index.html
ファイル内に、短い空白のHTMLページを追加します。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
</body>
</html>
このドキュメントにはいくつかの標準がありますタグと空 <body>
エレメント。
次に、 <script>
鬼ごっこ。 The src
スクリプトタグの属性は、作成しようとしている新しいJavaScriptファイルになります。 hello.js
:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script defer src="./hello.js"></script>
</head>
<body>
</body>
defer属性をに追加していることに注意してください。 <script>
鬼ごっこ。 これにより、ドキュメントが解析されるまでスクリプトタグの実行が遅れます。 延期しないと、次のようなエラーが表示される場合があります body
要素に追加しようとしても見つかりません。
次に、という名前のJavaScriptファイルを作成します hello.js
と同じディレクトリにありますindex.html
:
- nano hello.js
ファイル内にJavaScriptを記述して、テキストを含む新しいテキスト要素を作成します "Hello, World"
:
const el = document.createElement('h1');
const words = "Hello, World!"
const text = document.createTextNode(words);
el.appendChild(text);
document.body.appendChild(el);
スクリプトができたので、次のコマンドを開くことができます。 index.html
ブラウザのファイル。 あなたと同じディレクトリに index.html
ファイル、実行 npx serve
. これにより、serve パッケージが、にダウンロードせずにローカルで実行されます。 node_modules
. The serve
パッケージは、コードをローカルで提供する単純なWebサーバーを実行します。
npx serve
このコマンドは、パッケージをインストールするかどうかを尋ねます。 タイプ y
同意する:
Need to install the following packages:
serve
Ok to proceed? (y) y
コマンドを実行すると、次のような出力が表示されます。
npx: installed 88 in 15.187s
┌────────────────────────────────────────┐
│ │
│ Serving! │
│ │
│ Local: http://localhost:5000 │
│ │
│ Copied local address to clipboard! │
│ │
└────────────────────────────────────────┘
あなたがあなたのウェブブラウザを開いたとき http://localhost:5000
、コードが表示されます。 別のタブまたはウィンドウでサーバーを実行したままにするか、次のコマンドでサーバーを閉じることができます。 CTRL+C
コードをプレビューした後。
これで、ブラウザに基本的なページを表示していますが、サードパーティのコードとJavaScriptパッケージをまだ利用できません。 次のステップでは、ビルドツールを使用せずに、コードを動的にインポートし、関数をスクリプトにインポートします。
ステップ2—ES6モジュールを使用してHelloWorldスクリプトを作成する
このステップでは、外部パッケージを使用するコードを記述します。 ESインポートを使用してJavaScriptコードをインポートするようにコードを変更します。 最後に、を使用してブラウザにコードをロードします module
ブラウザがコードを動的にロードすることを認識できるように入力します。
開始するには、開きます hello.js
:
- nano hello.js
lodash からコードをインポートして、テキストを動的に変更します。
ファイル内で、テキストを次のように変更します。 Hello World
すべて小文字に: hello world
. 次に、ファイルの先頭で、startCase関数をからインポートします。 lodash
標準のES6を使用 import
構文:
import startCase from '@lodash/startCase';
const el = document.createElement('h1');
const words = "hello, world";
const text = document.createTextNode(words);
el.appendChild(text);
document.body.appendChild(el);
最後に、 startCase
とともに words
内部の引数としての変数 document.createTextNode
:
import startCase from '@lodash/startCase';
const el = document.createElement('h1');
const words = "hello, world";
const text = document.createTextNode(startCase(words));
el.appendChild(text);
document.body.appendChild(el);
Webサーバーを閉じた場合は、新しいターミナルウィンドウまたはタブを開いて実行します npx serve
サーバーを再起動します。 次に、に移動します http://localhost:5000
Webブラウザで変更を表示します。
ブラウザでコードをプレビューするときは、開発者コンソールを開きます。 これを行うと、エラーが表示されます。
OutputUncaught SyntaxError: Cannot use import statement outside a module
コードが使用しているので import
ステートメント、あなたは変更する必要があります <script>
内側のタグ index.html
現在複数のファイルに分割されているJavaScriptを処理します。 1つのファイルは、作成した元のコードです。 もう1つのファイルは、lodashからインポートされたコードです。 他のコードをインポートするJavaScriptコードは、モジュールと呼ばれます。
近い hello.js
開いて index.html
:
- nano index.html
スクリプトをモジュールとして実行するには、の値を変更します type
の属性 <script>
タグを付ける module
:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
注意してください、あなたはまた削除しました defer
属性。 JavaScriptモジュールは、ページが解析されるまで実行されません。
ブラウザを開いてもエラーが表示されます`:
OutputUncaught TypeError: Failed to resolve module specifier "@lodash/startCase". Relative references must start with either "/", "./", or "../"
今問題はではありません import
声明。 問題は、ブラウザが何を認識していないかです。 import
ステートメントは意味します。 Webサーバーでコードが見つかることを期待しているため、現在のファイルに関連するファイルを探します。 その問題を解決するには、という新しいツールが必要になります import maps
.
このステップでは、ESインポートを使用して外部ライブラリをロードするようにJavaScriptコードを変更する方法を学習しました。 HTMLも変更しました script
JavaScriptモジュールを処理するためのタグ。
次のステップでは、を使用してコードを見つける方法をブラウザに指示します import maps
.
ステップ3—インポートマップを使用した外部コードのロード
このステップでは、インポートマップを作成して、ブラウザに外部コードの場所を指示する方法を学習します。 また、モジュールコードをインポートする方法と、ブラウザでコードが遅延ロードされる方法についても学習します。
アン import map
キーがインポートの名前であるJavaScriptオブジェクトです(@lodash/startCase
)そして値はコードの場所です。
の中に index.html
新しいを追加します script
タグ付き type
の importmap
. の内部 script
タグ、キーを使用してJavaScriptオブジェクトを作成します imports
. 値は別のオブジェクトになります。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="importmap">
{
"imports": {
}
}
</script>
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
オブジェクトに末尾のコンマを追加しないように注意してください。 ブラウザはそれらを処理する方法を知りません。
これで基本オブジェクトができたので、コードの場所を追加できます。 インポートマップの構造は次のようになります。
{
"imports": {
"nameOfImport": "locationOfCode",
"nameOfSecondImport": "secondLocation"
}
}
あなたはすでにあなたの輸入品の名前を知っています @lodash/startCase
、しかし今、あなたはインポートマップを指す場所を見つける必要があります。
優れたリソースはunpkgです。 Unpkgは、次のパッケージのコンテンツ配信ネットワーク(CDN)です。 npm
. できれば npm install
パッケージの場合、unpkgを介してロードできるはずです。 Unpkgには、必要な特定のファイルを見つけるのに役立つブラウジングオプションも含まれています。
を見つけるには startCase
コード、ブラウザでhttps://unpkg.com/browse/[email protected]/を開きます。 単語に注意してください browse
URLで。 これにより、ディレクトリをグラフィカルに確認できますが、インポートマップにパスを追加しないでください。これは、生のJavaScriptファイルではなくHTMLページを提供するためです。
また、ブラウジングしていることに注意してください lodash-es
ではなく lodash
. これは lodash
この場合に必要になるのは、ESモジュールとしてエクスポートされたライブラリです。
コードを参照すると、startCase.jsというファイルがあることに気付くでしょう。 このコードは他の関数をインポートし、それらを使用して各単語の最初の文字を大文字に変換します。
import createCompounder from './_createCompounder.js';
import upperFirst from './upperFirst.js';
/**
* Converts `string` to
* [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
*
* @static
* @memberOf _
* @since 3.1.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the start cased string.
* @example
*
* _.startCase('--foo-bar--');
* // => 'Foo Bar'
*
* _.startCase('fooBar');
* // => 'Foo Bar'
*
* _.startCase('__FOO_BAR__');
* // => 'FOO BAR'
*/
var startCase = createCompounder(function(result, word, index) {
return result + (index ? ' ' : '') + upperFirst(word);
});
export default startCase;
ブラウザは次のようになります import
ステートメントを作成し、必要なすべてのファイルをインポートします。
インポートマップの場所が決まったので、ファイルインポートマップを新しいURLで更新します。 の中に index.html
、 追加 @lodash/startCase
URLと一緒に。 もう一度、必ず削除してください browse
:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="importmap">
{
"imports": {
"@lodash/startCase": "https://unpkg.com/[email protected]/startCase.js"
}
}
</script>
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
ファイルを保存します。 ブラウザを更新すると、 HelloWorldが表示されます。
注:インポートマップはまだ広くサポートされていません。 最新バージョンのEdgeまたはChromeでコードを開くか、でサポートされている最新のブラウザーを確認してください。
ブラウザに「HelloWorld」と表示されますが、さらに興味深いことが起こっています。 ブラウザでブラウザコンソールを開き、要素の検査を選択して、ネットワークタブに切り替えます。
ネットワークタブを開いた後、ページを更新すると、ブラウザがコードを動的に読み込んでいることがわかります。 新しいものを見つけたときはいつでも import
ステートメント、それは関連するコードをインポートします:
さらに重要なことに、すべてのコードが遅延ロードされることに注意してください。 つまり、ブラウザは、特に必要になるまでコードをインポートしません。 たとえば、 startCase
はインポートマップにあり、インポートマップはスクリプトの前に定義されています hello.js
、それは後までロードされません hello.js
コードをロードしてインポートします。
インポートマップに他のエントリを追加した場合、それらはコードにインポートされないため、ブラウザはそれらをまったくロードしません。 インポートマップは場所のマップであり、コード自体はインポートされません。
大きな問題の1つは、インポートマップがまだすべてのブラウザで完全にサポートされていないことです。 また、サポートされている場合でも、サポートされているブラウザを使用していないユーザーもいます。 幸い、完全なブラウザサポートを追加しながら、マップのインポート構文を使用するさまざまなプロジェクトがあります。
このステップでは、インポートマップを作成しました。 また、モジュールコードをインポートする方法と、コードがブラウザーに遅延ロードされる方法についても学習しました。 次のステップでは、SystemJSを使用してコードをインポートします。
ステップ4—SystemJSを使用したクロスブラウザーサポートの構築
このステップでは、SystemJSを使用してすべてのブラウザーでマップのインポートを使用します。 コードをSystemJSビルドとしてエクスポートし、インポートマップタイプをSystemJS形式を使用するように設定する方法を説明します。 この手順を完了すると、どのブラウザでもインポートマップを利用できるようになり、より複雑なアプリケーションやマイクロフロントエンドを構築するための基盤が整います。
マップをインポートすると、複雑なビルド手順の多くがアプリケーションから削除されますが、まだ広くサポートされていません。 さらに、すべてのライブラリがESモジュールとして構築されているわけではないため、コードでそれらを使用する方法にはいくつかの制限があります。
幸い、クロスブラウザサポート用のインポートマップの作成を使用し、さまざまなパッケージビルドを使用できるSystemJSというプロジェクトがあります。
lodashライブラリはES形式でコンパイルされるので便利ですが、ほとんどのライブラリには当てはまりません。 多くのライブラリは他の形式でエクスポートされます。 最も一般的なものの1つは、ユニバーサルモジュール定義またはUMDです。 この形式は、ブラウザとノードモジュールの両方で機能します。
主な違いは、ESインポートとは異なり、UMDビルドは通常すべてのコードを1つのファイルに結合することです。 ファイルははるかに大きくなり、おそらく実行するよりも多くのコードが含まれることになります。
SystemJSとlodashのUMDビルドを使用するようにプロジェクトを更新するには、最初に hello.js
:
- nano hello.js
変更 import
インポートするステートメント startCase
から直接機能 lodash
.
import { startCase } from 'lodash';
const el = document.createElement('h1');
const words = "hello, world";
const text = document.createTextNode(startCase(words));
el.appendChild(text);
document.body.appendChild(el);
ファイルを保存して閉じます。
次に、ファイルをSystemJSビルドとしてビルドするには、簡単なビルド手順が必要になります。 webpack などの別のビルドツールを使用できますが、この例ではrollupを使用します。
まず、プロジェクトを初期化して、 package.json
ファイル。 追加します -y
すべてのデフォルトを受け入れるフラグ:
npm init -y
コマンドを実行すると、成功の出力が表示されます。
{
"name": "hello",
"version": "1.0.0",
"description": "",
"main": "index.js",
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"homepage": ""
}
注:出力はバージョンによって若干異なる場合があります npm
使用しています。
次に、インストールします rollup
として devDepenceny
:
npm install --save-dev rollup
しばらくすると、成功メッセージが表示されます。
+ [email protected]
added 1 package from 1 contributor and audited 2 packages in 6.85s
found 0 vulnerabilities
次に、単純なビルド構成を作成します。 と呼ばれる新しいファイルを開きます rollup.config.js
:
- nano rollup.config.js
次に、SystemJS形式でコードを出力する構成を追加します。
export default {
external: ["lodash"],
input: ["hello.js"],
output: [
{
dir: "public",
format: "system",
sourcemap: true
}
]
};
The external
キーは、最終ビルドにlodashコードを含めないようにロールアップに指示します。 SystemJSは、インポート時にそのコードを動的にロードします。
The input
ルートファイルの場所です。 The output
ロールアップに、最終的なコードを配置する場所と、この場合は使用する必要のある形式を指示します system
.
ファイルを保存して閉じます。
ビルドステップが完了したので、それを実行するためのタスクを追加する必要があります。 開ける package.json
:
- nano package.json
の中に scripts
オブジェクト、というスクリプトを追加します build
それが実行されます rollup -c
. 変更 main
への鍵 hello.js
:
{
"name": "hello",
"version": "1.0.0",
"description": "",
"main": "hello.js",
"devDependencies": {
"rollup": "^2.56.2"
},
"scripts": {
"build": "rollup -c"
},
"keywords": [],
"author": "",
"license": "ISC",
"homepage": ""
}
ファイルを保存して閉じ、 build
指図:
npm run build
コマンドが短時間実行され、成功メッセージが表示されます。
> rollup -c
hello.js → public...
created public in 21ms
また、という新しいディレクトリが表示されます public
ビルドされたファイルが含まれます。 開いたら public/hello.js
プロジェクトがシステム形式でコンパイルされているのがわかります。
- nano public/hello.js
ファイルは次のようになります。 に似ています hello.js
周囲と System.register
方法。 さらに、 lodash
配列内にあります。 これにより、実行時に外部ライブラリをロードするようにSystemJSに指示されます。 メンテナの1人が、モジュール形式をさらに説明するビデオを作成しました。
System.register(['lodash'], function () {
'use strict';
var startCase;
return {
setters: [function (module) {
startCase = module.startCase;
}],
execute: function () {
const el = document.createElement('h1');
const words = "hello, world";
const text = document.createTextNode(startCase(words));
el.appendChild(text);
document.body.appendChild(el);
}
};
});
//# sourceMappingURL=hello.js.map
ファイルを保存して閉じます。
最後のステップは、 index.html
新しいファイルを処理するには:
開ける index.html
- nano index.html
まず、SystemJSコードをインポートする必要があります。 定期的に使用する <script>
のタグ src
CDNディストリビューションを指す属性。
置く <script>
インポートマップのすぐ下にタグを付けます。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="importmap">
{
"imports": {
"@lodash/startCase": "https://unpkg.com/lodash-es@4.17.21/startCase.js
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
次に、インポートマップを更新する必要があります。 形式は手順3で完了したものと似ていますが、次の3つの変更があります。
- インポートマップを更新します
type
. - 参照を更新します
lodash
. - への参照を追加します
hello.js
脚本。
まず、更新します type
. これはインポートマップのネイティブブラウザバージョンではないため、 systemjs
バージョン、タイプをに変更します systemjs-importmap
:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hello World</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="systemjs-importmap">
{
"imports": {
"@lodash/startCase": "https://unpkg.com/lodash-es@4.17.21/startCase.js
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
<script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>
次に、参照を更新します。 変化する @lodash/startCase
に lodash
. ライブラリ全体をインポートします。 次に、場所をunpkgでUMDビルドに変更します。
次に、の新しいエントリを追加します hello
そして、それをコンパイルされたバージョンに向けます public
ディレクトリ:
...
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="systemjs-importmap">
{
"imports": {
"hello": "./public/hello.js",
"lodash": "https://unpkg.com/[email protected]/lodash.js"
}
}
</script>
...
インポートしているので systemJS
インポートマップを更新しました。あとはモジュールをロードするだけです。
変更 type
の属性 script
モジュールのタグ systemjs-module
. 次に、 src
に import:hello
. これは教えてくれます systemjs
ロードするには hello
スクリプトと実行:
...
<script type="systemjs-importmap">
{
"imports": {
"hello": "./public/hello.js",
"lodash": "https://unpkg.com/[email protected]/lodash.js"
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
<script type="systemjs-module" src="import:hello"></script>
</head>
...
ファイルを保存して閉じます。
これを行うと、ブラウザが更新され、 HelloWorldが表示されます。
ネイティブインポートマップとは異なり、これはどのブラウザでも機能します。 FireFoxでの結果は次のとおりです。
ネットワークタブを見てください。 マップのインポートと同様に、コードは必要に応じて遅延ロードされることがわかります。
このステップでは、SystemJSを使用してブラウザー間でマップをインポートしました。 lodashのUMDビルドを使用するようにスクリプトを変更し、コードを出力するためのロールアップビルドを作成しました。 system
フォーマットし、インポートマップとモジュールタイプをSystemJSで動作するように変更しました
結論
このチュートリアルでは、インポートマップを使用してJavaScriptコードを動的にロードしました。 ビルドステップなしで外部ライブラリを動的にロードするアプリケーションをレンダリングしました。 次に、すべてのブラウザーでインポートマップを使用できるように、SystemJS形式でコードを生成するビルドプロセスを作成しました。
マップをインポートすると、大きなプロジェクトをmicrofrontendsと呼ばれる小さな独立した部分に分割し始める機会が得られます。 また、このチュートリアルで学習したように、静的に定義されたマップに制限する必要はありません。 他のスクリプトからロードできる動的インポートマップを作成することもできます。 scopes を使用して、それらをインポートするさまざまなスクリプトの依存関係のさまざまなバージョンを定義することにより、複数のプロジェクトに単一のインポートマップを使用することもできます。
進行中の新機能があり、公式仕様でそれらに従うことができます。