将大型Typescript项目转换为ES6模块 [英] Converting a large Typescript project to ES6 modules

查看:375
本文介绍了将大型Typescript项目转换为ES6模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当大的应用程序(约650个文件),目前有混合的ES6模块实现和旧的全局命名空间内部模块和类的实现。

I have a fairly large app (~650 files) that currently has a mixed implementation of ES6 modules and legacy global namespace internal modules and classes.

我想转移到100%ES6模块。

I want to move to 100% ES6 modules.

要实现这一点,我需要先进行转换通过添加 export关键字将所有全局对象添加到ES6模块。

To get there, I need to start by converting all the global objects to ES6 modules by adding the "export" keyword.

添加 export后,该全局对象不再是全局的,每个文件使用该对象的对象现在出现编译器错误找不到对象(即无法读取未定义的属性 xxx)。

As soon as I add "export", that global object is no longer global, and each file that uses that object now has a compiler error "object not found"(i.e. Cannot read property 'xxx' of undefined ).

要解决此问题,必须执行导入操作将其添加到文件中,从而将其转换为ES6模块,该模块依次反全球化该文件中的所有对象,从而在其他文件中引起新的找不到对象错误。

To fix this, an "import" must be added to the file, thus turning it into a ES6 module, which in turn "de-globalizes" all the objects in that file, causing new "object not found" errors in other files..

简而言之,这种迭代方法似乎效果不佳。

In short, this iterative approach doesn't seem like it will work well.


  1. 迭代在所有ts文件中

  1. Iterate over all ts files

  1. 以编程方式将 export 添加到所有顶级类,模块和变量。

  2. 将它们收集到列表中

  1. Programmatically add export to all top level classes, modules and variables.
  2. Gather these into a list


  • 生成桶(globalBarrel)文件,然后重新导出所有

  • 再次遍历所有ts文件

  • Generate a barrel (globalBarrel) file, re-exporting all the exports gathered in the previous step.
  • Iterate over all ts files again


    1. 向每个ts文件添加从 ./globalBarrel导入{列表,符号,由桶,文件导出} 到每个文件

    1. To each ts file, add import {list, of, symbols, exported, by, the, barrel,file} from "./globalBarrel" to each file


  • 编译干净吗?

  • Compile clean?


    1. 可能需要清理一些循环依赖问题。做到这一点。


  • 在以后编辑每个文件时,请使用vsCode组织导入命令删除许多不必要的文件。 / li>

  • As we edit each file in the future, use the vsCode " Organize Imports" command to remove the many unneeded.
  • 正如@ jfriend000所说:

    As @jfriend000 said:


    非模块化代码并尝试以编程方式将其转换为
    在模块中只会造成混乱。

    Taking non-modular code and trying to programmatically convert it to be in modules is just going to create a mess.

    一次将所有内容都放入模块将简化 true 模块化过程。

    But getting everything into modules all at once will make the true modularization process easier.

    这是解决此问题的最佳方法吗?有什么建议吗?

    Is this the the best way to go about this? Any suggestions?

    推荐答案


    要到达那里,我需要先将所有全局对象转换为通过添加 export关键字来构建ES6模块。

    To get there, I need to start by converting all the global objects to ES6 modules by adding the "export" keyword.

    我添加 export后,该全局对象不再是全局的,并且每个使用该对象的文件现在出现编译器错误找不到对象(即无法读取未定义的属性 xxx)。

    As soon as I add "export", that global object is no longer global, and each file that uses that object now has a compiler error "object not found"(i.e. Cannot read property 'xxx' of undefined ).

    要解决此问题,必须在文件中添加导入 ,因此将其转换为ES6模块,该模块进而取消全球化该文件中的所有对象,从而导致其他文件中出现新的找不到对象错误。

    To fix this, an "import" must be added to the file, thus turning it into a ES6 module, which in turn "de-globalizes" all the objects in that file, causing new "object not found" errors in other files..

    对。避免这种恶性循环的诀窍是,每次将文件转换为模块时,还要将该模块分配给一个全局变量,您可以从其他非模块文件中引用该全局变量,而无需将它们转换为模块。这需要一些样板。 此公开建议会稍微减少样板。

    Right. The trick to avoid this vicious cycle is, each time you convert a file to a module, also assign that module to a global variable that you can reference from other non-module files without turning them into modules. This takes some boilerplate; this open suggestion would reduce the boilerplate slightly.

    我假设您当前必须使用某种捆绑工具来确保所有非模块文件都已加载并有助于单个全局作用域,以便它们可以访问彼此的定义。首先使用以下代码创建文件,然后配置捆绑程序以确保其首先运行:

    I assume you must currently be using some kind of bundling tool to ensure that all your non-module files are loaded and contribute to a single global scope so they can access each other's definitions. Start by creating a file with the following code and configure your bundler to ensure that it runs first:

    namespace Modules {
        // Force `Modules` to be created at runtime.
        (() => {})();
    }
    

    现在,如果您开始使用:

    Now if you started with:

    // a.ts
    namespace A {
        export const a = 42;
    }
    
    // b.ts
    namespace B {
        console.log(A.a);
    }
    

    您可以过渡到:

    // a.ts
    export const a = 42;
    
    import * as A_ from "./a";
    declare global {
        namespace Modules {
            export import A = A_;
        }
    }
    Modules.A = A_;
    
    // b.ts
    namespace B {
        console.log(Modules.A.a);
    }
    

    b.ts 便可以访问具有完整类型信息的 Modules.A ,而无需自己成为模块本身(捆绑器的模数加载顺序问题)。

    and b.ts will be able to access Modules.A with full type information without becoming a module itself (modulo load order issues with your bundler).

    这篇关于将大型Typescript项目转换为ES6模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆