Mam funkcje IIFE dla niektórych kodów bibliotecznych w starszej aplikacji, która musi działać dla IE10 + (brak ładowania modułu ES6 itp.).
Zaczynam jednak opracowywać aplikację React, która będzie korzystała z ES6 i TypeScript, i chcę ponownie użyć kodu, który już mam, bez kopiowania plików. Po krótkich badaniach odkryłem, że chciałbym użyć wzorca UMD, aby umożliwić tym plikom biblioteki działanie zarówno jako <script src=*>
importowania, jak i umożliwić aplikacji React importowanie ich poprzez ładowanie modułu ES6.
Wymyśliłem następującą konwersję:
var Utils = (function(){
var self = {
MyFunction: function(){
console.log("MyFunction");
}
};
return self;
})();
do
(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");
};
})));
Umożliwi to ładowanie za pomocą Import Utils from './Utils.js'
polecenia, a także umożliwi wstawianie go za pomocą znacznika skryptowego<script src='Utils.js'></script>
Jednak niektóre z moich IIFE używają innych IIFE jako zależności (źle wiem, ale rzeczywistość).
var Utils = Utils; // Used to indicate that there is dependency on Utils
var RandomHelper = (function(){
var self = {
DoThing: function(){
Utils.MyFunction();
}
};
return self;
})();
Jeśli prawidłowo włączyć RandomHelper
i Utils
do plików, które mogą być importowane The React aplikacja nie jest kompatybilna z tą techniką. Robienie po prostu
Import Utils from './Utils.js'
Import RandomHelper from './RandomHelper.js'
nie działa, ponieważ uważam, że Utils nie ma zasięgu okna. Załaduje się bez problemu, ale RandomHelper.DoThing()
rzuci, że Utils nie jest zdefiniowane.
W starszej aplikacji
<script src='Utils.js'></script>
<script src='RandomHelper.js'></script>
działa bezbłędnie.
Jak mogę sprawić, by RandomHelper mógł używać Utils w aplikacji React, utrzymując kompatybilność z IE i ES5, ale nadal działając. Być może w jakiś sposób ustawiasz zmienną window / global?
PS: Rozumiem, że celem ładowania modułu ES6 jest radzenie sobie z zależnościami, a moje istniejące IIFE nie są idealne. Planuję w końcu zmienić klasy es6 i lepszą kontrolę zależności, ale na razie chcę korzystać z tego, co jest dostępne, bez przepisywania
źródło
Odpowiedzi:
Najpierw usuńmy to, funkcje modułu, jeśli nie zostaną wyraźnie wyeksportowane, są prywatnie objęte zakresem modułu definiującego . Nie da się obejść tego faktu. Istnieją jednak opcje obejścia, które możesz rozważyć.
1. Przyjęcie minimalnej modyfikacji starszego kodu jest dopuszczalne
Dzieło wokół z minimalnymi zmianami w kodzie starszych byłoby po prostu dodać
Utils
iRandomHelper
dowindow
obiektu. Na przykład zmieńvar Utils = (...)();
nawindow.Utils = (...)();
. W związku z tym obiekt będzie dostępny z obiektu globalnego zarówno przez starsze kody (ładowane przezimport
), jak i nowszą bazę kodów.2. Zakładając, że absolutnie żadna modyfikacja starszego kodu nie jest tolerowana
Nowy moduł ES6 powinien zostać utworzony jako serwer proxy do ładowania starszych skryptów:
Wreszcie, można importować
Utils
iRandomHelper
odlegacy-main.js
kiedy wymagane:źródło
Jednym z podejść, które można rozważyć, jest jakaś forma wstrzykiwania zależności : poproś aplikację React, aby otrzymywała RandomHelper lub niektóre jego właściwości ze świata zewnętrznego. Następnie możesz go usunąć, gdy będziesz gotowy do przecięcia przewodu.
źródło