依存関係解決
Parcelがソースコードをビルドする際、それは依存関係を検出します。これにより、コードを別々のファイルに分割し、複数の場所で再利用することが可能になります。依存関係は、依存するコードを含むファイルの場所と、そのビルド方法に関するメタデータを示します。
依存関係指定子
#依存関係指定子とは、インポートするファイルからの相対的な依存関係の場所を示す文字列です。例えば、JavaScriptでは、import
文またはrequire
関数が依存関係の作成に使用されます。CSSでは、@import
とurl()
が使用される場合があります。通常、これらの依存関係は完全な絶対パスを指定するのではなく、Parcelやその他のツールによって絶対パスに解決される短い指定子を使用します。
Parcelは、Nodeモジュール解決アルゴリズムの拡張バージョンを実装しています。これは、依存関係指定子をファイルシステムからロードできる絶対パスに変換する役割を担います。多くのツールでサポートされている標準的な依存関係指定子に加えて、Parcelはいくつかの追加の指定子タイプと機能もサポートしています。
相対指定子
#相対指定子は.
または..
で始まり、インポートするファイルからの相対パスでファイルを解決します。
import './utils.js';
import '../constants.js';
上記の例では、最初のインポートは/path/to/project/src/utils.js
に、2番目は/path/to/project/constants.js
に解決されます。
ファイル拡張子
#すべてのインポート指定子に完全なファイル拡張子を含めることをお勧めします。これにより、依存関係解決のパフォーマンスが向上し、あいまいさが減少します。
ただし、NodeのCommonJSとの互換性、およびTypeScriptとの互換性のために、Parcelは特定のファイルタイプについてはファイル拡張子を省略することを許可しています。省略できるファイル拡張子には、.ts
、.tsx
、.mjs
、.js
、.jsx
、.cjs
、および.json
が含まれます。他のすべてのファイルタイプをインポートするには、ファイル拡張子が必須です。
次の例は、上記と同じファイルに解決されます。
import './utils';
import '../constants';
これらは、JavaScriptまたはTypeScriptファイルからのインポートの場合にのみ省略できることに注意してください。HTMLやCSSなどの他のファイルタイプで定義された依存関係には、常にファイル拡張子が必須です。
TypeScriptファイルでは、Parcelは.js
、.jsx
、.mjs
、.cjs
などのJavaScript拡張子を、それらのTypeScript相当物(.ts
、.tsx
、.mts
、.cts
)に置き換えることも試みます。例えば、./foo.js
への依存関係は./foo.ts
に解決されます。これはTSCの動作と一致します。ただし、TSCとは異なり、元の./foo.js
が存在する場合は、TSバージョンではなく、元のファイルが使用されます。これはNodeや他のバンドラーの動作と一致します。
ディレクトリインデックスファイル
#JavaScript、TypeScript、その他のJSベースの言語では、依存関係指定子はファイルではなくディレクトリに解決される場合があります。ディレクトリにpackage.json
ファイルが含まれている場合、「パッケージエントリ」セクションで説明されているように、メインエントリが解決されます。package.json
が存在しない場合、ディレクトリ内のインデックスファイル(index.js
またはindex.ts
など)に解決しようとします。上記のすべての拡張子がインデックスファイルでサポートされています。
import './client';
例えば、/path/to/project/src/client
がディレクトリの場合、上記の指定子は/path/to/project/src/client/index.js
に解決される可能性があります。
ベア指定子
#ベア指定子は.
、/
、~
、または#
以外の文字で始まります。JavaScript、TypeScript、およびその他のJSベースの言語では、それらはnode_modules
内のパッケージに解決されます。HTMLやCSSなどの他のタイプのファイルでは、ベア指定子は相対指定子と同じように扱われます。
import 'react';
上記の例では、react
は/path/to/project/node_modules/react/index.js
のようなものになる可能性があります。正確な場所は、node_modules
ディレクトリの場所と、パッケージ内の設定によって異なります。
node_modules
ディレクトリは、インポートするファイルから上方に検索されます。検索はプロジェクトルートディレクトリで停止します。例えば、インポートするファイルが/path/to/project/src/client/index.js
にあった場合、次の場所が検索されます。
/path/to/project/src/client/node_modules/react
/path/to/project/src/node_modules/react
/path/to/project/node_modules/react
モジュールディレクトリが見つかると、パッケージエントリが解決されます。パッケージエントリでこのプロセスの詳細を参照してください。
パッケージサブパス
#ベア指定子は、パッケージ内のサブパスも指定できます。例えば、パッケージは単一のエントリポイントではなく、複数のエントリポイントを公開する場合があります。
import 'lodash/clone';
上記の例では、上記のようにnode_modules
ディレクトリ内でlodash
を解決し、そのメインエントリポイントではなく、パッケージ内のclone
モジュールを解決します。これは、例えばnode_modules/lodash/clone.js
ファイルである可能性があります。
組み込みモジュール
#Parcelには、path
やurl
など、多くの組み込みNode.jsモジュールのシムが含まれています。依存関係指定子がこれらのモジュール名のいずれかを参照する場合、同じ名前でnode_modules
にインストールされているモジュールよりも、組み込みモジュールが優先されます。Node環境向けにビルドする場合、組み込みモジュールはバンドルから除外されます。それ以外の場合は、シムが含まれます。組み込みモジュールの完全なリストについては、Nodeドキュメントを参照してください。
Electron環境向けにビルドする場合、electron
モジュールも組み込みと見なされ、バンドルから除外されます。
絶対指定子
#絶対指定子は/
で始まり、プロジェクトルートからの相対パスでファイルを解決します。プロジェクトルートはプロジェクトのベースディレクトリであり、通常はパッケージマネージャーのロックファイル(yarn.lock
やpackage-lock.json
など)、またはソース管理ディレクトリ(.git
など)が含まれています。絶対指定子は、深くネストされた階層で非常に長い相対パスを回避するために役立ちます。
import '/src/client.js';
上記の例は、プロジェクトのディレクトリ構造内の任意のファイル、任意の場所に配置でき、常に/path/to/project/src/client.js
に解決されます。
チルダ指定子
#チルダ指定子は~
で始まり、インポートするファイルから最も近いパッケージルートからの相対パスで解決されます。パッケージルートとは、package.json
ファイルのあるディレクトリであり、通常はnode_modules
内、またはモノレポのパッケージのルートにあります。チルダ指定子は、絶対指定子と同様の目的で使用されますが、複数のパッケージがある場合に特に便利です。
import '~/src/utils.js';
上記の例は/path/to/project/packages/frontend/src/utils.js
に解決されます。
ハッシュ指定子
#ハッシュ指定子は#
文字で始まり、その動作は含まれるファイルタイプによって異なります。JavaScriptおよびTypeScriptファイルでは、ハッシュ指定子は以下で説明する内部パッケージインポートとして扱われます。その他のファイルでは、これらは相対URLハッシュとして扱われます。
package.json
の"imports"
フィールドを使用して、パッケージ内のJavaScriptまたはTypeScriptファイルのインポート指定子に適用されるプライベートマッピングを定義できます。これにより、パッケージは環境に応じて条件付きインポートを定義できます。これは、下記とNode.jsドキュメントで説明されています。
{
"imports": {
"#dep": {
"node": "dep-node",
"browser": "dep-browser"
}
}
}
import '#dep';
クエリパラメータ
#依存関係指定子には、解決されたファイルの変換オプションを指定するクエリパラメータを含めることもできます。たとえば、イメージをロードするときに幅と高さを指定してサイズ変更することができます。
.logo {
background: url(logo.png?width=400&height=400);
}
イメージの詳細については、イメージトランスフォーマーのドキュメントを参照してください。カスタムトランスフォーマープラグインでもクエリパラメータを使用できます。
注記: クエリパラメータは、CommonJS指定子(require
関数によって作成される)ではサポートされていません。
URLスキーム
#依存関係指定子は、URLスキームを使用して名前付きパイプラインをターゲットにすることができます。これにより、デフォルトのパイプラインとは異なるパイプラインでファイルをコンパイルするように指定できます。たとえば、bundle-text:
スキームを使用して、コンパイルされたバンドルをテキストとしてインライン化できます。バンドルインライン化の詳細を参照してください。
名前付きパイプラインには使用できず、組み込みの動作を持つ予約済みのURLスキームがいくつかあります。
node:
– 組み込みNodeモジュールを指定する別の方法です。組み込みモジュールを参照してください。npm:
– URL依存関係(HTML、CSS、またはWebワーカーなど)がnode_modules
パッケージからファイルを取り込むための方法です。http:
およびhttps:
– 完全修飾URL依存関係。これらは実行時に解決され、Parcelによって変更されません。data:
– 依存関係のソースコードをインラインで含むデータURL。現在Parcelでは実装されていませんが、将来の使用のために予約されています。file:
– ファイルURL。将来の使用のために予約されています。mailto:
およびtel:
- 一般的に使用されるURLスキーム。これらはParcelによって変更されません。
Glob指定子
#ParcelはGlobを使用して一度に複数のファイルをインポートすることをサポートしますが、Globインポートは非標準であるため、デフォルトのParcel設定には含まれていません。有効にするには、@parcel/resolver-glob
を.parcelrc
に追加します。
{
"extends": "@parcel/config-default",
"resolvers": ["@parcel/resolver-glob", "..."]
}
有効にすると、./files/*.js
のような指定子を使用して複数のファイルをインポートできます。これは、ファイル名に対応するキーを持つオブジェクトを返します。
import * as files from './files/*.js';
は次のものと同等です
import * as foo from './files/foo.js';
import * as bar from './files/bar.js';
let files = {
foo,
bar
};
具体的には、globパターンの動的な部分はオブジェクトのキーになります。動的な部分が複数ある場合は、ネストされたオブジェクトが返されます。例えば、pages/profile/index.js
ファイルが存在する場合、以下のようにマッチします。
import * as pages from './pages/*/*.js';
console.log(pages.profile.index);
これは、bundle-text:
のようなURLスキームにも、動的インポートにも有効です。動的インポートを使用する場合、結果のオブジェクトにはファイル名と関数のマッピングが含まれます。各関数は、解決されたモジュールをロードするために呼び出すことができます。つまり、各ファイルはすべて事前にロードするのではなく、オンデマンドでロードされます。
let files = import('./files/*.js');
async function doSomething() {
let foo = await files.foo();
let bar = await files.bar();
return foo + bar;
}
Globはnpmパッケージからファイルを取り込むためにも使用できます。
import * as locales from '@company/pkg/i18n/*.js';
console.log(locales.en.message);
GlobインポートはCSSでも機能します。
@import "./components/*.css";
は次のものと同等です
@import "./components/button.css";
@import "./components/dropdown.css";
パッケージエントリ
#パッケージディレクトリを解決する際、package.json
ファイルを参照してパッケージエントリを決定します。Parcelは次のフィールドを(順に)確認します。
source
– モジュールがシンボリックリンクの背後にある場合(例:モノレポ内、またはnpm link
経由)、Parcelはsource
フィールドを使用してソースからモジュールをコンパイルします。source
フィールドは、パッケージに複数のエントリポイントがある場合のエイリアスマッピングとしても使用できます。詳細は下記のエイリアスを参照してください。exports
– パッケージエクスポート、詳細は下記を参照してください。browser
– パッケージのブラウザ固有バージョン。ブラウザ環境向けにビルドする場合、browser
フィールドは他のフィールドよりも優先されます。browser
フィールドは、パッケージに複数のエントリポイントがある場合のエイリアスマッピングとしても使用できます。詳細は下記のエイリアスを参照してください。module
– パッケージのESモジュールバージョン。main
– パッケージのCommonJSバージョン。
これらのフィールドのいずれも設定されていない場合、またはそれらが指すファイルが存在しない場合、解決はインデックスファイルにフォールバックします。詳細はディレクトリインデックスファイルを参照してください。
パッケージエクスポート
#package.json
の"exports"
フィールドを使用して、パッケージのパブリックにアクセス可能なエントリポイントを定義できます。これらは、環境に基づいて条件付きの動作を定義することもでき、モジュールがどこからインポートされるか(例:ノードまたはブラウザ)によって解決が変わるようにすることができます。
パッケージエクスポートの有効化
#パッケージエクスポートは、考慮されていない既存のプロジェクトを壊す可能性があるため、デフォルトで無効になっています。プロジェクトルートディレクトリのpackage.json
ファイルに以下を追加することで、サポートを有効にできます。
{
"@parcel/resolver-default": {
"packageExports": true
}
}
単一エクスポート
#パッケージにエクスポートされるモジュールが1つしかない場合、"exports"
フィールドは文字列として定義できます。
{
"name": "foo",
"exports": "./dist/index.js"
}
上記の例でユーザーが"foo"
パッケージをインポートすると、node_modules/foo/dist/index.js
モジュールが解決されます。
複数エクスポート
#パッケージが複数のモジュールをエクスポートする場合、"exports"
フィールドは、これらの各エクスポートを見つける場所を定義するマッピングを提供できます。"."
エクスポートはメインエントリポイントを定義し、他のエントリはサブパスとして定義されます。
{
"name": "foo",
"exports": {
".": "./dist/index.js",
"./bar": "./dist/bar.js"
}
}
上記のパッケージでは、ユーザーは"foo"
をインポートできます(これはnode_modules/foo/dist/index.js
に解決されます)。または"foo/bar"
をインポートできます(これはnode_modules/foo/dist/bar.js
に解決されます)。
"exports"
フィールドを含むパッケージによって明示的にエクスポートされていないサブパスは、コンシューマーからアクセスできません。たとえば、上記のパッケージで"foo/abc"
をインポートしようとすると、ビルド時のエラーが発生します。
*
文字は、エクスポートマッピング内でワイルドカードとして使用できます。マッピングの左辺には1つの*
しか表示できず、一致した文字列は右辺の各インスタンスに置き換えられます。これにより、エクスポートするすべてのファイルを個別にリストする必要がなくなります。
{
"name": "foo",
"exports": {
"./*": "./dist/*.js"
}
}
上記の例では、dist
ディレクトリ内のすべての.js
ファイルが、拡張子なしでパッケージからエクスポートされます。たとえば、"foo/bar"
をインポートすると、node_modules/foo/dist/bar.js
に解決されます。
条件付きエクスポート
#"exports"
フィールドは、異なる環境またはその他の条件で同じ指定子に対して異なるマッピングを定義することもできます。たとえば、パッケージはESモジュールとCommonJS、またはNodeとブラウザに対して異なるエントリポイントを提供できます。
{
"name": "foo",
"exports": {
"node": "./dist/node.js",
"default": "./dist/default.js"
}
}
上記の例では、コンシューマーがNode環境から"foo"
モジュールをインポートした場合、node_modules/foo/dist/node.js
に解決されます。それ以外の場合は、node_modules/foo/default.js
に解決されます。
条件付きエクスポートは、サブパスマッピング内にネストすることもできます。
{
"name": "foo",
"exports": {
"./bar": {
"node": "./dist/bar-node.js",
"default": "./dist/bar-default.js"
}
}
}
これにより、"foo/bar"
をインポートして、Nodeとその他の環境で異なるファイルに解決できます。
条件付きエクスポートは、互いにネストしてより複雑なロジックを作成することもできます。
{
"name": "foo",
"exports": {
"node": {
"import": "./dist/node.mjs",
"require": "./dist/node.cjs"
},
"default": "./dist/default.js"
}
}
上記の例では、パッケージがNode環境内でESM import
またはCommonJS require
を介してロードされるかどうかによって、モジュールの異なるバージョンが定義されています。
Parcelは次のエクスポート条件をサポートしています。
"import"
– パッケージはESMimport
構文を使用して参照されました。"require"
– パッケージはCommonJSrequire
関数を使用して参照されました。"module"
– パッケージはESMimport
構文またはCommonJSrequire
関数のいずれかから参照されました。"sass"
– パッケージはSassスタイルシートから参照されました。"less"
– パッケージはLessスタイルシートから参照されました。"stylus"
– パッケージはStylusスタイルシートから参照されました。"style"
– パッケージはスタイルシート(例:CSS、Sass、Stylusなど)から参照されました。"node"
– 出力はNode環境で実行されます。"browser"
– 出力はブラウザ環境で実行されます。"worker"
– 出力はWebワーカーまたはサービスワーカー環境で実行されます。"worklet"
– 出力はworklet環境で実行されます。"electron"
– 出力はElectron環境で実行されます。"development"
– パッケージは開発ビルドでロードされました。"production"
– パッケージは本番ビルドでロードされました。"default"
– 他の条件が一致しなかった場合のデフォルトの条件。
エクスポート条件が解決される順序は、上記にリストされている順序ではなく、package.json
で定義されている順序に従います。
その他の例
#package.json
エクスポートの詳細については、Node.jsドキュメントを参照してください。
エイリアス
#エイリアスを使用して、依存関係の通常の解決をオーバーライドできます。たとえば、API互換の異なる代替でモジュールをオーバーライドしたり、CDNからロードされたライブラリによって定義されたグローバル変数に依存関係をマッピングしたりする場合があります。
エイリアスは、package.json
のalias
フィールドを介して定義されます。依存関係を含むソースファイルに最も近いpackage.json
でローカルに定義することも、プロジェクトルートディレクトリのpackage.json
でグローバルに定義することもできます。グローバルエイリアスは、node_modules
内のファイルやパッケージを含む、プロジェクト内のすべてのファイルやパッケージに適用されます。
パッケージエイリアス
#パッケージエイリアスは、node_modules
依存関係を異なるパッケージ、またはプロジェクト内のローカルファイルにマッピングします。たとえば、プロジェクト内のファイルとnode_modules
内の他のライブラリの両方でreact
とreact-dom
をPreactで置き換えるには、プロジェクトルートディレクトリのpackage.json
にグローバルエイリアスを定義できます。
{
"alias": {
"react": "preact/compat",
"react-dom": "preact/compat"
}
}
エイリアスが定義されているpackage.json
からの相対パスを使用して、モジュールをプロジェクト内のファイルにマッピングすることもできます。
{
"alias": {
"react": "./my-react.js"
}
}
モジュールの特定のサブパスのみをエイリアスすることもサポートされています。この例では、lodash/clone
をtiny-clone
にエイリアスします。lodash
パッケージ内の他のインポートは影響を受けません。
{
"alias": {
"lodash/clone": "tiny-clone"
}
}
これは逆にも機能します。モジュール全体がエイリアスされている場合、そのパッケージのサブパスインポートはすべて、エイリアスされたモジュール内で解決されます。たとえば、lodash
をmy-lodash
にエイリアスしてlodash/clone
をインポートした場合、これはmy-lodash/clone
に解決されます。
ファイルエイリアス
#エイリアスは、パッケージ内の特定のファイルを別のファイルで置き換える相対パスとして定義することもできます。これは、alias
フィールドを使用してファイルを無条件に置き換えるか、source
またはbrowser
フィールドを使用して条件付きで置き換えることができます。これらのフィールドの詳細については、上記のパッケージエントリを参照してください。
たとえば、特定のファイルをブラウザ固有のバージョンで置き換えるには、browser
フィールドを使用できます。
{
"browser": {
"./fs.js": "./fs-browser.js"
}
}
これで、ブラウザ環境でmy-module/fs.js
がインポートされると、実際にはmy-module/fs-browser.js
が取得されます。これは、外部からのインポート(例:パッケージサブパス)と、モジュール内の内部の両方にも適用されます。
Globエイリアス
#ファイルエイリアスは、globを使用して定義することもできます。これにより、単一のパターンを使用して多くのファイルを置き換えることができます。置換には、キャプチャされたglobマッチにアクセスするための$1
などのパターンを含めることができます。これは、alias
フィールドを使用してファイルを無条件に置き換えるか、source
またはbrowser
フィールドを使用して条件付きで置き換えることができます。これらのフィールドの詳細については、上記のパッケージエントリを参照してください。
たとえば、source
フィールドを使用して、パッケージ内のコンパイル済みコードと元のソースコード間のマッピングを提供できます。モジュールがシンボリックリンクされている場合、またはモノレポ内にある場合、これにより、Parcelは事前にコンパイルされたバージョンを使用するのではなく、ソースからモジュールをコンパイルできます。
{
"source": {
"./dist/*": "./src/$1"
}
}
これで、dist
ディレクトリ内のファイルがインポートされるたびに、代わりにsrc
フォルダー内の対応するファイルがロードされます。
Shimエイリアス
#ファイルまたはパッケージは、ビルドから除外され、空のモジュールで置き換えられるようにfalse
にエイリアスできます。これは、たとえばNode.jsでのみ動作する特定のモジュールをブラウザビルドから除外する場合に役立ちます。
{
"alias": {
"fs": false
}
}
グローバルエイリアス
#ファイルまたはパッケージは、ランタイムで定義されるグローバル変数にエイリアスすることもできます。たとえば、特定のライブラリはCDNからロードできます。それをバンドルする代わりに、そのライブラリへの依存関係が解決されるたびに、バンドルされる代わりに、そのグローバル変数への参照で置き換えられます。
これは、global
プロパティを持つオブジェクトへのエイリアスを作成することで実現できます。次の例では、jquery
依存関係指定子をグローバル変数$
にエイリアスしています。
{
"alias": {
"jquery": {
"global": "$"
}
}
}
TSConfig
#Parcelは、TypeScriptのtsconfig.json
設定ファイルで定義されているいくつかの設定をサポートしています。これには、baseUrl
、paths
、moduleSuffixes
が含まれます。Parcelは、依存関係を含むファイルから上方向に検索して、最も近いtsconfig.json
ファイルを見つけます。また、extends
オプションを使用して、複数のtsconfigの設定をマージすることもサポートしています。詳細は、TypeScriptドキュメントを参照してください。
baseUrl
#baseUrl
フィールドは、ベア指定子を解決するためのベースディレクトリを定義します。
{
"compilerOptions": {
"baseUrl": "./src"
}
}
import 'Home';
上記の例では、Home
は存在する場合はsrc/Home.js
に解決されます。存在しない場合は、例えばnode_modules/Home
にフォールバックします。
paths
#paths
フィールドを使用して、ベア指定子からファイルパスへのマッピングを定義できます。*
文字を使用してワイルドカードパターンを定義することもできます。
paths
フィールドで参照されるファイルパスは、baseUrl
が定義されている場合はbaseUrl
を基準に、そうでない場合はtsconfig.json
ファイルを含むディレクトリを基準にします。
{
"compilerOptions": {
"paths": {
"jquery": ["./vendor/jquery/dist/jquery"],
"app/*": ["./src/app/*"]
}
}
}
import 'jquery';
import 'app/foo';
上記の例では、jquery
は./vendor/jquery/dist/jquery.js
に、app/foo
は./src/app/foo.js
に解決されます。
moduleSuffixes
#moduleSuffixes
フィールドを使用すると、モジュールを解決する際に検索するファイル名のサフィックスを指定できます。
{
"compilerOptions": {
"moduleSuffixes": [".ios", ".native", ""]
}
}
import './foo';
上記の例では、Parcelは./foo.ios.ts
、./foo.native.ts
、./foo.ts
(.tsx
、.js
などの他の拡張子の他に)を検索します。
その他のツールの設定
#このセクションでは、Nodeの解決アルゴリズムに対するParcelの拡張機能と連携するように、その他のツールを設定する方法について説明します。
TypeScript
#絶対パス指定子、チルダ依存関係指定子、エイリアスなどのParcel機能をサポートするには、TypeScriptの設定が必要です。これは、tsconfig.json
のpaths
オプションを使用して行うことができます。詳細は、TypeScriptモジュール解決ドキュメントを参照してください。
例えば、チルダパスをルートディレクトリにマップするには、この設定を使用できます。
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~*": ["./*"]
}
}
}
URLスキームのサポートは、プロジェクトに環境モジュール宣言を作成することでも有効にできます。例えば、bundle-text:
スキームで読み込まれた依存関係を文字列にマップするには、次の宣言を使用できます。これは、プロジェクト内の任意の場所にparcel.d.ts
などのファイルに配置できます。
declare module 'bundle-text:*' {
const value: string;
export default value;
}
Flow
#絶対パス指定子、チルダ指定子、エイリアスをサポートするには、Flowの設定が必要です。これは、.flowconfig
のmodule.name_mapper機能を使用して行うことができます。
例えば、絶対パス指定子をプロジェクトルートから解決するようにマップするには、この設定を使用できます。
[options]
module.name_mapper='^\/\(.*\)$' -> '<PROJECT_ROOT>/\1'
URLスキームを有効にするには、期待される型をエクスポートする.flow
宣言ファイルへのマッピングを作成する必要があります。例えば、bundle-text:
スキームで読み込まれた依存関係を文字列にマップするには、bundle-text.js.flow
というファイルを作成し、そのスキームを参照するすべての依存関係をそれにマップできます。
// @flow
declare var value: string;
export default value;
[options]
module.name_mapper='^bundle-text:.*$' -> '<PROJECT_ROOT>/bundle-text.js'