ES6変数のインポート名はnode.jsにありますか?


108

ES6インポートを使用しているときに、変数名を提供するモジュールに何かをインポートすることは可能ですか?

つまり、構成で提供された値に応じて、実行時にいくつかのモジュールをインポートします。

import something from './utils/' + variableName;

1
@Bigoodはい、コンパイラがスローし、Webstormにもエラーが表示されます
Vytautas Butkus

回答:


67

importステートメントではありません。importまたexport、静的に分析できるように定義されているため、ランタイム情報に依存できません。

ローダーAPI(ポリフィル)を探していますが、仕様のステータスが少しわかりません。

System.import('./utils/' + variableName).then(function(m) {
  console.log(m);
});

3
システムを「要求」する必要がありますか?グローバルスコープではありません。Ps私はbabel jsを使用しています
Vytautas Butkus

まだどこにも実装されていません。リンクからポリフィルを使用する必要があります。
Felix Kling

1
ただ、それはちょっと(ファイルをロードしようとする)動作しますが、その後、他のモジュールのパスを台無しに、確認...あまりにも悪いのそれがネイティブにサポートされていない...
ビトータス・バカス

3
これはまだ問題ですか?..私はdinamically ES6モジュールをロードする必要がありますが、私は成功を持っていなかった
calbertts

26

Felixの回答に加えて、これは現在ECMAScript 6文法では許可されていないことを明示しておきます。

ImportDeclaration

  • import ImportClause FromClause;

  • 輸入 ModuleSpecifier;

FromClause

  • ModuleSpecifier から

ModuleSpecifier

  • 文字列リテラル

A ModuleSpecifierは唯一の可能StringLiteral、ないような表現の他の種類AdditiveExpression


2
const string literals を含めるように拡張されなかったのは残念です。それらは静的に分析可能ですよね?依存関係の場所を再利用する可能性があります。(たとえば、テンプレートをインポートし、テンプレートとテンプレートの場所の両方を使用できるようにします)。
nicodemus13 2017年

26

これは実際には動的インポートではありませんが(たとえば、私の状況では、以下でインポートするすべてのファイルは、実行時に選択されずに、webpackによってインポートおよびバンドルされます)、特定の状況で役立つ可能性がある使用しているパターンは、 :

import Template1 from './Template1.js';
import Template2 from './Template2.js';

const templates = {
  Template1,
  Template2
};

export function getTemplate (name) {
  return templates[name];
}

または代わりに:

// index.js
export { default as Template1 } from './Template1';
export { default as Template2 } from './Template2';


// OtherComponent.js
import * as templates from './index.js'
...
// handy to be able to fall back to a default!
return templates[name] || templates.Template1;

で簡単にデフォルトに戻すことはできないと思いますrequire()。存在しない構築されたテンプレートパスをインポートしようとすると、エラーがスローされます。

requireとimportの良い例と比較はここにあります:http : //www.2ality.com/2014/09/es6-modules-final.html

@iainastacioからの再エクスポートに関する優れたドキュメント:http ://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

このアプローチに関するフィードバックを聞きたいです:)


賛成票。私は「または代替の」アプローチを使用しました。私のカスタムローカリゼーションソリューションの魅力のように働きました。
groundh0g 2018


1
私はこれを考えるべきだった。どのようにインポートする場合でも(何もインポートしない場合でも)優れたソリューションです。後で名前を取得したい、または名前で取得したいアイテムのリストがありますか?それらを配列リテラルではなくオブジェクトリテラルに入れ、オブジェクトの構文がローカルの定数/変数名に基づいて名前を付けるようにします。それらをリストとして再び必要とする場合は、実行してくださいObject.values(templates)
Andrew Koster

15

ESモジュールの動的インポートと呼ばれる新しい仕様があります。基本的に、あなたは電話するだけimport('./path/file.js')でいいのです。関数はpromiseを返します。これは、インポートが成功した場合にモジュールで解決されます。

async function importModule() {
   try {
      const module = await import('./path/module.js');
   } catch (error) {
      console.error('import failed');
   }
}

ユースケース

ユースケースには、React、Vueなどのルートベースのコンポーネントのインポートや、モジュール遅延ロードする機能が含まれますランタイム中に必要になったときにが含まれます。

さらに詳しい情報

これはGoogle Developersの説明です。

ブラウザーの互換性(2020年4月)

MDNによると、これは現在のすべての主要なブラウザー(IEを除く)でサポートされており、caniuse.comは世界市場シェア全体で87%のサポートを示しています。繰り返しになりますが、IEやChrome以外のEdgeではサポートされていません。


あなたはあなたの編集について確信していますか?提案は、可変パスを使用した例を示しています:github.com/tc39/proposal-dynamic-import#example
phil294

@Blauhirn私はそうでしたが、あなたのリンクはそれが可能性であることを明確に示しています。私はWebPACKのは、例えばこれらの輸入解決だろうか見当がつかないが
ニコライ・シュミット

私が間違っている場合は私を修正しますが、webpackはこれらを処理しませんか?ブラウザーで「そのまま」実行することが動的インポートのポイントだと思いました。
phil294 2018年

はい、そのままブラウザで実行できます。ただし、webpackは自動的にインポートを使用して、ルートなど、アプリのさまざまな部分に対してアプリを複数のバンドルに分割します。私はいつもそれらを使用していて、本当に役に立ちます。「処理」に関する限り、webpackはインポートにbabelを渡します。これにより、古いブラウザーの機能がポリフィルされます。
Nicolai Schmid

明確にする必要があります:動的import()変数で機能し、静的に分析可能である必要はありません(これが「動的」の要点ですよね?)。私の答えを見てください。
Velojet

6

importNode.jsでES6について具体的に尋ねられた質問を理解していますが、以下は、より一般的なソリューションを探している他の人に役立つ場合があります。

let variableName = "es5.js";
const something = require(`./utils/${variableName}`);

ES6モジュールインポートしていてdefaultエクスポートにアクセスする必要がある場合は、次のいずれかを使用する必要があります。

let variableName = "es6.js";

// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;

// Accessing
const something = require(`./utils/${variableName}`);
something.default();

このアプローチでデストラチャを使用することもできます。これにより、他のインポートの構文に慣れ親しむことができます。

// Destructuring 
const { someMethod } = require(`./utils/${variableName}`);    
someMethod();

残念ながら、default破壊だけでなくアクセスしたい場合は、これを複数のステップで実行する必要があります。

// ES6 Syntax
Import defaultMethod, { someMethod } from "const-path.js";

// Destructuring + default assignment
const something = require(`./utils/${variableName}`);

const defaultMethod = something.default;    
const { someMethod, someOtherMethod } = something;

4

それには、ES6以外の表記を使用できます。これは私のために働いたものです:

let myModule = null;
if (needsToLoadModule) {
  myModule = require('my-module').default;
}

3

私はこの構文はあまり好きではありませんが、機能します:
書く代わりに

import memberName from "path" + "fileName"; 
// this will not work!, since "path" + "fileName" need to be string literal

次の構文を使用します。

let memberName = require("path" + "fileName");

1
@UlysseBN悪い点で違う?または本当に重要ではない方法?
サム

@Jacob彼らは本当に完全に異なっているので、ええ、あなたが何をしているのかに依存して問題になるかもしれません。最初の構文は静的に評価されますが、2番目の構文は動的に評価されます。したがって、たとえば、webpackを使用している場合は、2番目のツリーでツリーを正しく振ることはできません。他にも多くの違いがあります。ドキュメントを読んで、どちらが適切かを確認することをお勧めします。
Ulysse BN

@Jacob-本当に問題はありません(ほとんどの場合)。require()初期バージョンである、ファイルをロードするためのNode.JSメソッドです。importステートメントは新しいバージョンで、公式の言語構文の一部になりました。ただし、多くの場合、ブラウザは(科学の背後にある)以前のブラウザを使用します。requireステートメントはファイルをキャッシュするので、ファイルが2回目に読み込まれると、メモリから読み込まれます(パフォーマンスが向上します)。インポートの方法には、WebPackを使用している場合、それ自体に利点があります。その後、webpackはデッドリファレンスを削除できます(これらのスクリプトはクライアントにダウンロードされません)。
Gil Epshtain

1

ダイナミックimport()(Chrome 63以降で利用可能)があなたの仕事をします。方法は次のとおりです。

let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });

0

私はこのようにします

function load(filePath) {
     return () => System.import(`${filePath}.js`); 
     // Note: Change .js to your file extension
}

let A = load('./utils/' + variableName)

// Now you can use A in your module

0

./utils/test.js

export default () => {
  doSomething...
}

ファイルから呼び出す

const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.