ES6 모듈 가져 오기를 통해 레거시 JS 모듈 (예 : IIFE)로드 및 소비


9

나는이 인생 레거시 (legacy) 애플리케이션에 라이브러리 코드의 일부 기능을하는 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'

유틸리티가 창 범위가 아니라고 생각하기 때문에 작동하지 않습니다. 문제없이로드되지만 RandomHelper.DoThing()Utils가 정의되어 있지 않습니다.

레거시 앱에서

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

완벽하게 작동합니다.

RandomHelper가 React 앱에서 Utils를 사용하여 IE와 ES5를 호환 가능하게 유지하면서도 반응을 유지하려면 어떻게해야합니까? 아마도 어떻게 든 창 / 전역 변수를 설정합니까?

추신 : ES6 모듈 로딩의 요점은 종속성을 다루는 것이며 기존의 IIFE는 이상적이지 않다는 것을 알고 있습니다. 결국 es6 클래스와 더 나은 종속성 제어를 전환하려고하지만 지금은 다시 작성하지 않고 사용할 수있는 것을 사용하고 싶습니다.


4
React는 jsx를 사용하고 브라우저가 jsx를 이해하지 못하므로 babel이 필요합니다. 어쨌든 babel을 사용해야하기 때문에 반응 프로젝트에서 import 문을 사용하지 않아도됩니다. React도 OO에서 멀어지고 있으므로 반응과 함께 ES6 클래스를 사용한다고 말하는 것은별로 의미가 없습니다. 여전히 클래스를 지원하지만 기능적 구성 요소로 이동하고 있습니다.
HMR

예, babel / webpack이 있고 CRA 프레임 워크를 사용합니다.
ParoX

node.js에서 global.Utils = (func ... 및 var Utils = global.Utils;)를 사용할 수도 있습니다.
Tom

당신이 지원해야 할 것에 따라 상상할 수 있는 스텐실로 웹 구성 요소를 좋아할 수 있습니다.
Chris W.

1
새 앱에서 사용하려는 모든 항목에 대해 ES6 가져 오기 구문으로 이동하여 레거시 응용 프로그램의 IIFE (또는 단순히 UMD) 형식으로 다시 변환해야한다고 생각합니다. 완전한 파일을 다시 작성할 필요는 없지만 종속성 선언을 수정하십시오.
Bergi

답변:


2

먼저 이것을 피하십시오. 명시 적으로 내 보내지 않으면 모듈 기능은 정의하는 모듈에 개인적으로 범위가 지정됩니다 . 이 사실을 해결할 수 없습니다. 그러나 고려할 수있는 해결 방법이 있습니다.

1. 레거시 코드의 최소한의 수정이 허용된다고 가정

레거시 코드를 최소한으로 변경하여 해결하는 방법은 단순히 객체 를 추가 Utils하고 추가 RandomHelper하는 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

당신이 고려할 수있는 한 가지 접근법은 일종의 의존성 주입입니다 .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.