ES6 modülü içe aktarmaları yoluyla eski JS modüllerini (ör. IIFE'ler) yükleme ve tüketme


9

IE10 + (ES6 modülü yükleme yok, vb.) İçin çalışması gereken eski bir uygulamada bazı kütüphane kodu için IIFE işlevleri var .

Ancak, ES6 ve TypeScript kullanacak bir React uygulaması geliştirmeye başladım ve dosyaları çoğaltmadan zaten sahip olduğum kodu yeniden kullanmak istiyorum. Biraz araştırma yaptıktan sonra, bu kütüphane dosyalarının hem <script src=*>içe aktarma olarak çalışmasına hem de React uygulamasının ES6 modülü yüklemesi yoluyla içe aktarmasına izin vermek için bir UMD kalıbı kullanmak istediğimi buldum .

Aşağıdaki dönüşümü buldum:

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

için

(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");
    };
})));

Bu, Import Utils from './Utils.js'komut aracılığıyla yüklemeye ve ayrıca bir komut dosyası etiketi kullanılarak eklenmesine izin verir<script src='Utils.js'></script>

Bununla birlikte, IIFE'mden bazıları diğer IIFE'leri bağımlılık olarak kullanıyor (kötü biliyorum ama gerçek).

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

Doğru açarsanız RandomHelperve Utilsalınabilir dosyalar halinde, uygulama, bu teknikle uyumlu değildir yanıt verin. Basitçe

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

çalışmıyor çünkü Utils'in pencere kapsamı olmadığına inanıyorum. Sorunsuz bir şekilde yüklenir, ancak RandomHelper.DoThing()Utils'in tanımlanmadığını atar.

Eski uygulamada

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

kusursuz çalışır.

RandomHelper'ın bir React uygulamasında Utils'i nasıl kullanabileceğimi, IE ve ES5 uyumlu tuttuğunu, ancak yine de reaksiyonda çalışabileceğini nasıl anlayabilirim. Belki bir şekilde bir pencere / genel değişken ayarlıyor?

Not: ES6 modülünün yüklenmesinin, bağımlılıklarla uğraşmak olduğunu ve mevcut IIFE'lerimin ideal olmadığını anlıyorum. Sonunda es6 sınıflarını ve daha iyi bağımlılık kontrolünü değiştirmeyi planlıyorum ama şimdilik yeniden yazma olmadan mevcut olanı kullanmak istiyorum


4
React jsx kullanır ve hiçbir tarayıcı jsx'i anlamaz, bu yüzden yine de babel'e ihtiyacınız vardır, yine de babel'i kullanmak zorunda olduğunuz için bir reaksiyon projesinde içe aktarma ifadelerini kullanmanın bir anlamı yoktur. Reaksiyon da OO'dan uzaklaşıyor, bu nedenle ES6 sınıflarını reaksiyonla kullanmak istediğinizi söylemek pek mantıklı değil. Hala sınıfları desteklemekle birlikte fonksiyonel bileşenlere doğru ilerliyor.
HMR

Evet babil / webpack'im var ve CRA çerçevesini kullanıyorum.
ParoX

Node.js'de global.Utils = (işlev ... ve var Utils = global.Utils; sonra da kullanabilirim)
Tom

Desteklemek için neye bağlı olarak hayal bazı stenciljs ile üzerine bazı web bileşeni aşk ovmak olabilir.
Chris W.

1
Yeni uygulamanızda kullanmak istediğiniz her şey için gerçekten ES6 içe aktarım sözdizimine geçmeniz ve eski uygulama için IIFE (veya yalnızca UMD) biçimine geri aktarmanız gerektiğini düşünüyorum. Dosyanın tamamını yeniden yazmak zorunda değilsiniz, ancak bağımlılık bildirimlerini düzeltin.
Bergi

Yanıtlar:


2

Öncelikle bunu önleyelim, açıkça dışa aktarılmadıysa modül özellikleri özel olarak tanımlayan modüle dahil edilir . Bu gerçeğin üstesinden gelemezsin. Ancak düşünebileceğiniz geçici seçenekler var.

1. Eski kodda minimum değişiklik yapılması kabul edilebilir

Eski koduna minimal değişikliklerle etrafında bir çalışma basitçe eklemek olacaktır Utilsve RandomHelperhiç windowbir nesne. Örneğin, değiştirmek var Utils = (...)();için window.Utils = (...)();. Sonuç olarak, nesneye hem eski kodlar (aracılığıyla yüklenir import) hem de daha yeni kod tabanı tarafından genel nesneden erişilebilir .

2. Eski kodda hiçbir değişiklik kesinlikle kabul edilemezse

Eski komut dosyalarını yüklemek için proxy olarak yeni bir ES6 modülü oluşturulmalıdır:

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

Son olarak, gerektiğinde içeri Utilsve RandomHelperdışarı aktarabilirsiniz legacy-main.js:

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

Utils.MyFunction()
RandomHelper.DoThing()

0

Düşünebileceğiniz bir yaklaşım bir çeşit bağımlılık enjeksiyonudur : React uygulamanızın dış dünyadan RandomHelper veya bazı özelliklerinden yararlanmasını sağlayın. Ardından, kabloyu kesmeye hazır olduğunuzda çıkarabilirsiniz.

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.