让我们先解决这个问题,如果未显式导出模块特征,则将其私有范围限定为定义模块
我对需要运行IE10 +的旧版应用程序中的某些库代码具有IIFE功能(不加载ES6模块等)。>>
但是,我开始开发将使用ES6和TypeScript的React应用,我想重复使用已有的代码而不复制文件。经过一番研究,我发现我想使用UMD模式来允许这些库文件既可以作为<script src=*>
导入,又可以让React应用通过ES6模块加载来导入它们。
我想出了以下转换:
var Utils = (function(){ var self = { MyFunction: function(){ console.log("MyFunction"); } }; return self; })();
to
(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; })();
如果正确地将
RandomHelper
和Utils
转换为可以导入的文件,则React应用程序与此技术不兼容。简单地做Import Utils from './Utils.js' Import RandomHelper from './RandomHelper.js'
无效,因为我认为实用程序不在窗口范围内。它将毫无问题地加载,但是
RandomHelper.DoThing()
将抛出未定义实用程序的信息。在旧版应用中
<script src='Utils.js'></script> <script src='RandomHelper.js'></script>
完美运行。
我如何使RandomHelper能够在React应用程序中使用Utils,使其与IE和ES5兼容,但仍可以在react中工作。也许以某种方式设置窗口/全局变量?
PS:我知道ES6模块加载的重点是处理依赖关系,而我现有的IIFE并不理想。我计划最终切换es6类和更好的依赖关系控制,但现在我想使用可用的内容而无需重写
我对需要在IE10 +上运行的旧版应用程序中的某些库代码具有IIFE功能(无需加载ES6模块等)。但是,我开始开发一个React应用,它将是...
让我们先解决这个问题,如果未显式导出模块特征,则将其私有范围限定为定义模块
只需对旧版代码进行最少的更改,便可以简单地将Utils
和RandomHelper
添加到window
对象。例如,将var Utils = (...)();
更改为window.Utils = (...)();
。因此,旧代码(通过import
加载)和更新的代码库都可以从全局对象访问该对象。
应该创建一个新的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
导入RandomHelper
和legacy-main.js
:import { Utils, RandomHelper } from './legacy-main.js' Utils.MyFunction() RandomHelper.DoThing()
您可以考虑的一种方法是dependency injection的某种形式:让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>
让我们先解决这个问题,如果未显式导出模块特征,则将其私有范围限定为定义模块
您可以考虑的一种方法是dependency injection的某种形式:让React应用从外界接收RandomHelper或其中的某些属性。然后,当您准备切断电源线时,可以将其删除。