ES6モジュールのインポートを介してレガシーJSモジュール(例:IIFE)をロードして使用する


9

私が持っている生命維持の IE10 +(ノーES6モジュールのロードなど)のために働く必要があるとレガシー・アプリケーションのライブラリのコードの一部についての機能を。

しかし、私はES6とTypeScriptを使用するReactアプリの開発を開始しており、ファイルを複製せずに既存のコードを再利用したいと考えています。少し調べた結果、UMDパターンを使用して、これらのライブラリファイルを<script src=*>インポートとして機能させ、ReactアプリがES6モジュールの読み込みを介してインポートできるようにしたいと思いました。

私は次の変換を思いつきました:

var Utils = (function(){
  var self = {
    MyFunction: function(){
      console.log("MyFunction");
    }
  };
  return self;
})();

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (factory((global.Utils = {})));
}(this, (function (exports) { 
  exports.MyFunction = function(){
      console.log("MyFunction");
    };
})));

これにより、Import Utils from './Utils.js'コマンドによる読み込みが可能になり、スクリプトタグを使用して挿入することもできます<script src='Utils.js'></script>

しかし、私のIIFEの一部は他のIIFEを依存関係として使用しています(私が知っているのは悪いが現実です)。

var Utils = Utils; // Used to indicate that there is dependency on Utils
var RandomHelper = (function(){
  var self = {
    DoThing: function(){
      Utils.MyFunction();
    }
  };
  return self;
})();

正しく有効にした場合RandomHelperUtils、インポートできるファイルに、アプリはこの技術と互換性がありません反応します。単純に

Import Utils from './Utils.js'
Import RandomHelper from './RandomHelper.js'

Utilsはウィンドウスコープではないため、機能しません。問題なく読み込まれますがRandomHelper.DoThing()、Utilsが定義されていないことがスローされます。

レガシーアプリ

<script src='Utils.js'></script>
<script src='RandomHelper.js'></script>

完璧に動作します。

RandomHelperがReactアプリでUtilsを使用できるようにして、IEとES5の互換性を維持しながら、リアクティブで動作させるにはどうすればよいですか。おそらく、どういうわけかウィンドウ/グローバル変数を設定していますか?

PS:ES6モジュールのロードのポイントは依存関係を処理することであり、既存のIIFEは理想的ではないことを理解しています。私は最終的にes6クラスとより良い依存関係制御を切り替える予定ですが、今のところ、書き直さなくても利用できるものを使用したいと思います


4
Reactはjsxを使用し、ブラウザーはjsxを理解しないため、とにかくbabelが必要です。とにかくbabelを使用する必要があるため、reactプロジェクトでimportステートメントを使用しないことはできません。ReactもOOから離れているため、reactでES6クラスを使用したいというのはあまり意味がありません。それはまだクラスをサポートしますが、機能コンポーネントに向かっています。
HMR

はい、babel / webpackを使用しており、CRAフレームワークを使用しています。
ParoX

Node.jsの中で私はまた、global.Utils =(FUNC ...とVARのUtils = global.Utilsを使用することができ、その後、。
トム・

あなたがサポートする必要に応じて、私が想像するいくつかのステンシルでWebコンポーネントの愛をこすることができます。
Chris W.

1
新しいアプリで使用するすべてのものをES6インポート構文に移行し、レガシーアプリケーションのIIFE(または単にUMD)形式に変換し直す必要があると思います。ファイル全体を書き直す必要はありませんが、依存関係の宣言を修正してください。
Bergi、

回答:


2

最初にこれを解決しましょう。モジュールの機能は、明示的にエクスポートされていない場合は、プライベートにスコープを定義モジュールに限定しています。この事実を回避することはできません。ただし、考慮できる回避策のオプションがあります。

1.従来のコードの最小限の変更が許容できると想定

お使いのレガシーコードに最小限の変更で回避するには、単に追加することですUtilsRandomHelperするwindowオブジェクト。たとえば、に変更var Utils = (...)();window.Utils = (...)();ます。その結果、オブジェクトは、(を介してロードされたimport)レガシーコードと新しいコードベースの両方によってグローバルオブジェクトからアクセス可能になります。

2.レガシーコードの変更は絶対に許容されないと仮定する

レガシースクリプトをロードするためのプロキシとして、新しいES6モジュールを作成する必要があります。

// ./legacy-main.js

const utilsScript = await fetch( './Utils.js' )
const randomHelperScript = await fetch( './RandomHelper.js' )

const utilsScriptText = await utilsScript.text()
const randomHelperScriptText = await randomHelperScript.text()

// Support access to `Utils` via `import` 
export const Utils = Function( `${utilsScriptText}; return Utils;` )()
// Additionally support access via global object 
Object.defineProperty(window, 'Utils', { value: Utils })

// Support access to `RandomHelper` via `import`
// Note that `Utils` which is a dependency for `RandomHelper` ought to be explicitly injected
// into the scope of execution of `RandomHelper`.
export const RandomHelper = Function( 'Utils', `${randomHelperScriptText}; return RandomHelper;` )( Utils )
// Additionally support access via global object 
Object.defineProperty(window, 'RandomHelper', { value: RandomHelper })

最後に、あなたがインポート可能UtilsRandomHelperからlegacy-main.js、必要な場合:

import { Utils, RandomHelper } from './legacy-main.js'

Utils.MyFunction()
RandomHelper.DoThing()

0

検討できるアプローチの1つは、依存性注入の形式です。ReactアプリにRandomHelperまたはそのプロパティの一部を外部から受信させます。次に、コードを切る準備ができたら、それを取り外します。

var Utils = (function(){
  var self = {
    MyFunction: function(name){
      return `Hello, ${name}!`;
    }
  };
  return self;
})();

var RandomHelper = (function(){
  var self = {
    DoThing: function(name){
      return Utils.MyFunction(name);
    }
  };
  return self;
})();

const ComponentOne = ({hello}) => {
  return <h1>{hello('ComponentOne')}</h1>;
}

const ComponentTwo = ({hello}) => {
  return <h2>{hello('ComponentTwo')}</h2>
}

const App = ({ExternalFunctions}) => {
  return (
    <header>
      <ComponentOne hello={ExternalFunctions.hello} />
      <ComponentTwo hello={ExternalFunctions.hello} />
    </header>
  )
}

ReactDOM.render(
  <App ExternalFunctions={{hello: RandomHelper.DoThing}} />,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.