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


9

对于具有旧版本的应用程序中的某些库代码,我具有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()会抛出未定义实用程序的情况。

在旧版应用中

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

完美地工作。

我如何让RandomHelper能够在React应用程序中使用Utils,使其与IE和ES5兼容,但仍可以在react中工作。也许以某种方式设置窗口/全局变量?

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


4
React使用jsx,并且没有浏览器能够理解jsx,因此无论如何您都需要babel,在react项目中不使用import语句是没有用的,因为无论如何您都必须使用babel。React也正在远离OO,因此说要使用带React的ES6类没有多大意义。它仍然支持类,但是正在向功能组件发展。
HMR

是的,我有babel / webpack,并且使用了CRA框架。
ParoX

在node.js中,我还可以使用global.Utils =(func ...和var Utils = global.Utils;然后。-
汤姆(Tom)

我可以根据需要支持的模板,用一些stenciljs摩擦一些Web组件的爱。
克里斯·

1
我认为您真的应该为要在新应用程序中使用的所有内容转移到ES6导入语法,然后将其重新转换为旧版应用程序的IIFE(或简称为UMD)格式。您不必重写完整的文件,而是修复依赖项声明。
Bergi

Answers:


2

首先让我们解决这个问题,如果未显式导出模块功能,则它们将私下作用于定义模块。您无法绕开这个事实。但是,您可以考虑一些解决方法。

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

以最小的改动你的遗留代码相关工作将是简单的添加UtilsRandomHelperwindow对象。例如,更改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,并RandomHelperlegacy-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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.