javascript - 通过 ES6 模块导入加载和使用旧版 JS 模块(例如 IIFE)

标签 javascript reactjs es6-modules legacy iife

我有IIFE旧应用程序中需要适用于 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到可以导入的文件中,React 应用程序与此技术不兼容。简单做事

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 应用程序中使用 Utils,保持 IE 和 ES5 兼容,但仍然可以在 React 中工作。也许以某种方式设置窗口/全局变量?

PS:我知道 ES6 模块加载的目的是处理依赖关系,而我现有的 IIFE 并不理想。我计划最终切换 es6 类和更好的依赖控制,但现在我想使用可用的内容而无需重写

最佳答案

让我们首先解决这个问题,模块功能,如果没有显式导出,则将私有(private)地限定在定义模块中。你无法回避这个事实。但您可以考虑一些解决方法。

1。假设对遗留代码的最小修改是可以接受的

对旧代码进行最小更改的解决方法是简单地将 UtilsRandomHelper 添加到 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 })

最后,您可以在需要时从 legacy-main.js 导入 UtilsRandomHelper:

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

Utils.MyFunction()
RandomHelper.DoThing()

关于javascript - 通过 ES6 模块导入加载和使用旧版 JS 模块(例如 IIFE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58470020/

相关文章:

javascript - jQuery Cycle - 挤压图像?

javascript - 使用 for 循环和 setTimeout 在 ES6 中修改 React Elements

javascript - 使用innerHTML从数据库填充表单组件

javascript - Tipue 搜索 (Jquery)

reactjs - 使用 React + Material UI Card Expander 扩展单个卡片

javascript - 是否可以访问 React Navigation 的 navigationOptions 中的非静态方法?

javascript - 如何在加载事件中加载 html 页面中的 es6 模块

reactjs - 如何在下一个 js 中从节点模块外部的文件夹中导入模块

javascript - 在输入帧时播放视频

node.js - 将文件下载从 protected 路径传递到浏览器