web-dev-qa-db-ja.com

ES6モジュールを条件付きでインポートする方法を教えてください。

私は以下のようなことをする必要があります。

if (condition) {
    import something from 'something';
}
// ...
if (something) {
    something.doStuff();
}

上記のコードはコンパイルされません。それはSyntaxError: ... 'import' and 'export' may only appear at the top levelを投げます。

here のようにSystem.importを使ってみましたが、Systemがどこから来たのかわかりません。受け入れられなかったのはES6の提案ですか?その記事からの "programmatic API"へのリンクは私を 廃止予定のdocsページ にダンプします。

139
ericsoco

ECMAを使用した動的輸入提案があります。これはステージ3にあります。これは babel-preset としても利用可能です。

以下はあなたの場合のように条件付きレンダリングをする方法です。

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}

これは基本的に約束を返します。約束の決議は、モジュールを持っていると予想されます。この提案には、複数の動的インポート、デフォルトのインポート、jsファイルのインポートなどの他の機能もあります。 動的インポートの詳細については、 を参照してください。

89
thecodejack

ご希望の場合は、requireを使うことができます。これは条件付きrequireステートメントを持つ方法です。

let something = null;
let other = null;

if (condition) {
    something = require('something');
    other = require('something').other;
}
if (something && other) {
    something.doStuff();
    other.doOtherStuff();
}
83
BaptWaels

条件付きでインポートすることはできませんが、逆のことができます。条件付きで何かをエクスポートする。それはあなたのユースケースに依存します、従ってこの回避策はあなたのためではないかもしれません。

できるよ:

api.js

import mockAPI from './mockAPI'
import realAPI from './realAPI'

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

私はこれを使用してmixpanelなどの分析ライブラリを偽装しています。現在、複数のビルドやフロントエンドを持つことはできません。最もエレガントではありませんが、うまくいきます。ミックスパネルの場合は初期化が必要なので、環境によっては、あちこちに「if」がいくつかあります。

38
Kev

答えは、今のところ、あなたはできないということです。

http://exploringjs.com/es6/ch_modules.html#sec_module-loader-api

その目的はできる限り静的解析を可能にすることであり、条件付きでインポートされたモジュールはそれを打ち破ります。また言及する価値があります - 私は Babel を使用しています、そしてSystemはBabelではサポートされていないと思いますES6規格.

9
ericsoco

require()は実行時にモジュールをインポートする方法であり、文字列リテラルパスと共に使用される場合はimportのように静的解析にも適しています。これは、バンドルの依存関係を選択するためにバンドル担当者が必要とするものです。

const defaultOne = require('path/to/component').default;
const NamedOne = require('path/to/component').theName;

完全な静的分析サポートを備えた動的モジュール解決のために、最初にインデクサー(index.js)にモジュールを索引付けし、ホストモジュールにインデクサーをインポートします。

// index.js
export { default as ModuleOne } from 'path/to/module/one';
export { default as ModuleTwo } from 'path/to/module/two';
export { SomeNamedModule } from 'path/to/named/module';

// Host.js
import * as indexer from 'index';
const moduleName = 'ModuleOne';
const Module = require(indexer[moduleName]);
2
Shoaib Nawaz

動的インポートの仕組みを明確に理解するには、この例をご覧ください。

動的モジュールのインポートの例

モジュールのインポートとエクスポートの基本を理解するため。

JavaScriptモジュールGithub

Javascript Modules MDN

0
Ashok R

条件付きインポートは三項とrequire()sでも達成できます。

const logger = DEBUG ? require('dev-logger') : require('logger');

この例は、ES Lintのglobal-requireドキュメントから取得したものです。 https://eslint.org/docs/rules/global-require

0
Elliot Ledger

私はすぐに呼び出される関数とrequireステートメントを使ってこれを達成することができました。

const something = (() => (
  condition ? require('something') : null
))();

if(something) {
  something.doStuff();
}
0
bradley2w1dl

evalでそれを曖昧にすることは私のために働きました、静的なアナライザからそれを隠して...

if (typeof __CLI__ !== 'undefined') {
  eval("require('fs');")
}
0
Chris Marstall