Tải và tiêu thụ các mô-đun JS cũ (ví dụ IIFE) thông qua nhập mô-đun ES6


9

Tôi có các hàm IIFE cho một số mã thư viện trong một ứng dụng cũ cần hoạt động cho IE10 + (Không tải mô-đun ES6, v.v.).

Tuy nhiên, tôi đang bắt đầu phát triển ứng dụng React sẽ sử dụng ES6 và TypeScript và tôi muốn sử dụng lại mã mà tôi đã có mà không cần sao chép các tệp. Sau một chút nghiên cứu, tôi thấy rằng tôi muốn sử dụng mẫu UMD để cho phép các tệp thư viện này hoạt động như <script src=*>nhập khẩu và cho phép ứng dụng React nhập chúng thông qua tải mô-đun ES6.

Tôi đã đưa ra các chuyển đổi sau đây:

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

đến

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

Điều này sẽ cho phép tải thông qua Import Utils from './Utils.js'lệnh và cũng cho phép nó được chèn bằng thẻ script<script src='Utils.js'></script>

Tuy nhiên, một số IIFE của tôi sử dụng các IIFE khác như một sự phụ thuộc (xấu tôi biết nhưng thực tế).

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

Nếu biến chính xác RandomHelperUtilsthành các tệp có thể được nhập, ứng dụng React không tương thích với kỹ thuật này. Làm đơn giản

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

không hoạt động vì tôi tin Utils không nằm trong phạm vi cửa sổ. Nó sẽ tải mà không có vấn đề nhưng RandomHelper.DoThing()sẽ ném rằng Utils không được xác định.

Trong ứng dụng cũ

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

hoạt động hoàn hảo.

Làm cách nào để RandomHelper có thể sử dụng Utils trong ứng dụng React, giữ cho nó tương thích với IE và ES5 nhưng vẫn hoạt động bình thường. Có lẽ bằng cách nào đó thiết lập một cửa sổ / biến toàn cầu?

PS: Tôi hiểu rằng quan điểm của việc tải mô-đun ES6 là để đối phó với các phụ thuộc và IIFE hiện tại của tôi không lý tưởng. Tôi dự định cuối cùng sẽ chuyển đổi các lớp es6 và kiểm soát phụ thuộc tốt hơn nhưng hiện tại tôi muốn sử dụng những gì có sẵn mà không cần viết lại


4
React sử dụng jsx và không có trình duyệt nào hiểu jsx nên dù sao bạn cũng cần babel, không có cách nào để không sử dụng câu lệnh nhập trong dự án phản ứng vì dù sao bạn cũng phải sử dụng babel. React cũng đang rời khỏi OO, vì vậy nói rằng bạn muốn sử dụng các lớp ES6 với React không có ý nghĩa gì nhiều. Nó vẫn hỗ trợ các lớp nhưng đang chuyển sang các thành phần chức năng.
HMR

Có, tôi có babel / webpack và tôi sử dụng khung CRA.
ParoX

Trong node.js tôi cũng có thể sử dụng global.Utils = (func ... và var Utils = global.Utils; sau đó.
Tom

Có thể chà một số thành phần web tình yêu trên nó với một số stprintjs tôi tưởng tượng tùy thuộc vào những gì bạn cần hỗ trợ.
Chris W.

1
Tôi nghĩ rằng bạn thực sự nên chuyển sang cú pháp nhập ES6 cho mọi thứ bạn muốn sử dụng trong ứng dụng mới của mình và chuyển nó trở lại định dạng IIFE (hoặc đơn giản là UMD) cho ứng dụng cũ. Bạn không phải viết lại tập tin hoàn chỉnh, nhưng sửa các khai báo phụ thuộc.
Bergi

Câu trả lời:


2

Trước tiên, hãy giải quyết vấn đề này, các tính năng mô-đun, nếu không được xuất khẩu rõ ràng, sẽ nằm trong phạm vi riêng tư của mô-đun xác định . Bạn không thể hiểu được sự thật này. Nhưng có những lựa chọn xung quanh bạn có thể xem xét.

1. Giả sử sửa đổi tối thiểu mã kế thừa là chấp nhận được

Một công việc xung quanh với những thay đổi tối thiểu đối với mã kế thừa của bạn sẽ chỉ đơn giản là thêm UtilsRandomHelpervào windowđối tượng. Ví dụ, thay đổi var Utils = (...)();thành window.Utils = (...)();. Do đó, đối tượng sẽ có thể truy cập được từ đối tượng toàn cầu bằng cả mã kế thừa (được tải qua import) và cơ sở mã mới hơn.

2. Giả sử hoàn toàn không có sửa đổi trong mã kế thừa có thể được chấp nhận

Một mô-đun ES6 mới phải được tạo như một proxy để tải các tập lệnh kế thừa:

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

Cuối cùng, bạn có thể nhập UtilsRandomHelpertừ legacy-main.jskhi được yêu cầu:

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

Utils.MyFunction()
RandomHelper.DoThing()

0

Một cách tiếp cận bạn có thể xem xét là một số hình thức tiêm phụ thuộc : ứng dụng React của bạn nhận RandomHelper hoặc một số thuộc tính của nó từ thế giới bên ngoài. Sau đó, bạn có thể loại bỏ nó khi bạn đã sẵn sàng để cắt dây.

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.