Завантажте та споживайте застарілі модулі JS (наприклад, IIFE) через імпорт модуля ES6


9

У мене є функції IIFE для деякого коду бібліотеки у застарілому додатку, який повинен працювати для IE10 + (Не завантажується модуль ES6 тощо).

Однак я починаю розробляти додаток React, який використовуватиме ES6 та TypeScript, і я хочу повторно використовувати код, який у мене вже є, не дублюючи файли. Після невеликих досліджень я виявив, що хотів би використовувати шаблон 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;
})();

Якщо правильно включити RandomHelperі Utilsв файли , які можуть бути імпортовані, то Реагувати програма не сумісна з цією технікою. Робити просто

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, підтримуючи сумісність IE та ES5, але все ще працює в реакції. Можливо, якось встановити вікно / глобальну змінну?

PS: Я розумію, що сенс завантаження модуля ES6 - це впоратися із залежностями, і мої існуючі IIFE не є ідеальними. Я планую врешті-решт переключити класи es6 та покращити контроль залежності, але поки що я хочу використовувати те, що є, без переписування


4
React використовує jsx, і жоден веб-переглядач не розуміє jsx, тому вам потрібен babel, все-таки не потрібно використовувати заяви про імпорт в реагуванні проекту, оскільки ви все одно повинні використовувати babel. React також віддаляється від OO, тому сказати, що ви хочете використовувати ES6-класи з react не має особливого сенсу. Він все ще підтримує класи, але рухається до функціональних компонентів.
HMR

Так, у мене є babel / webpack, і я використовую рамку CRA.
ParoX

У node.js Я можу також використовувати global.Utils = (FUNC ... і вар Utils = global.Utils ;. Потім
Том

Чи можна натерти якусь любов до веб-компонентів якимись трафаретами, які я думаю, залежно від того, що вам потрібно підтримати.
Кріс В.

1
Я думаю, ви дійсно повинні перейти до синтаксису імпорту ES6 для всього, що ви хочете використовувати у своєму новому додатку, і перекласти його назад у формат IIFE (або просто UMD) для застарілого додатка. Вам не доведеться переписувати весь файл, але виправляйте декларації залежності.
Берги

Відповіді:


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 })

Нарешті, ви можете імпортувати Utilsі RandomHelperз 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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.