Webpack每个条目模块解析别名规则

时间:2019-05-24 13:32:56

标签: webpack

这里很长。即使我对答案或解决方案的期望不高(或没有任何期望),仍然感觉像是一个要共享/尝试的有趣的问题。

我有什么

我有一个带有2个入口点的应用。它们都导入同一个文件main.ts,而文件又导入了一个Handlebars模板main.hbs

entry1.ts
└ main.ts
  ├ main.hbs
  └ …
entry2.ts
└ main.ts
  ├ main.hbs
  └ …

main.ts还导入了其他TS类(数千个),这些类又导入了其他HBS模板(数百个),但是几乎所有这两个类在两个条目之间共享。这些条目只需使用某些特定于条目的选项从main.ts调用Main类即可。

我需要什么

有人要求我为HBS模板创建特定于条目的“变体”,以便entry1将加载main.v1.hbs,而entry2将加载main.v2.hbs(如果有这样的文件)存在。并且,如果其他任何导入的.ts文件也导入了其他任何.hbs文件,它们还将返回各自的*.v1.hbs / *.v2.hbs变体。

由于我希望它尽可能自动化,并且对实际源代码的更改尽可能少,所以我决定要走的路是让Webpack“重定向”导入:

  • entry1.ts导入main.ts导入main.hbs实际加载main.v1.hbs
    • main.ts导入的menu.ts实际上加载了menu.v1.hbs
    • 依此类推...
  • entry2.ts导入main.ts导入main.hbs实际加载main.v2.hbs
    • main.ts导入的menu.ts实际上加载了menu.v2.hbs
    • 依此类推...

我认为这种方法会给我带来很多好处:

  1. 不必更改所需文件中的源代码(实际上是数百个文件)。

    如果我对此不关心,则可以使用require with expression,然后使用摇树来仅保留每个条目中使用的模板。但是...

    • 这会增加编译时间和复杂性
    • 如果无法正确摇晃树,并且必须将所有变体实际存储在一个束中,那么我可以在运行时访问正确的束(eww),从而大大增加束的大小
    • 我身上整洁的怪胎并不热衷于处理更多的东西只是为了扔掉它们
    • 该方法似乎仅适用于require()语法,而不适用于ES样式的静态import,因此与前向兼容
  2. 甚至可以在“重定向”之前检查是否存在变体文件,如果不存在,则回退到默认文件。

    重要的是,随着创建了更多新的“ v2”变体文件,这些文件使我可以逐步进行此过渡,而无需保持静态导入列表以映射到哪个文件或其他文件。 / p>

  3. 也许可以在一次编译运行中进行此转换。

    如果我不在乎,我可以单独编译每个条目,并在每次运行时设置适当的选项。但是,该应用程序非常大,需要花费几分钟才能构建,甚至需要增加Node内存限制。因此,按顺序或并行构建每个条目并不是太好了,尽管如果没有其他方法,这是我的最后选择。无论如何,考虑到Webpack的功能,我觉得这是我应该可以在单个构建中完成的事情。

我尝试过的

NormalModuleReplacementPlugin

这是Webpack内置的插件,乍一看似乎可以满足我的需要:拦截require对特定模块的调用并将其更改为其他模块,它甚至还具有正则表达式和谓词功能支持。但是,由于映射在编译期间无法更改,因此我很快放弃了这一点。这意味着我不能为每个条目设置不同的替换规则。

Writing my own Loader

现在,我们深入战es。我想,为什么不写自己的装载机来解决这个问题?加载器is capable读取其根条目,因此从理论上讲,我应该能够使用该信息来代替main.hbsmain.v1.hbs和{{1 }} entry1

尽管这最初看起来很有效(尽管我讨厌这种方法的非无状态性),但我发现Webpack似乎在第一次执行时就缓存了需求/解决方案:在处理main.v2.hbs时。因此,即使具有所有逻辑,我的加载程序每个文件也仅被调用一次,而不是每个entry2被调用一次,而且我无法实现我想要的目标。

我研究了告诉Webpack“不要缓存它,下次再读”的方法,我没有运气。由于两个条目都导入main.ts,而后者仅导入一次require,因此Webpack会将TS和HBS都视为仅1个模块,而不管它们是否导入到多个条目文件中。我想这是必须要做的优化,但是对于这种特定情况,我没有找到解决的办法。

Writing my own Plugin

由于装载机无法满足我的需求,因此我尝试编写插件。我浏览了详细的文档,并尝试使用main.tsmain.hbs,但是并没有太过深入。我浏览了compiler的{​​{3}},并以相同的方式插入了compilation(文档似乎没有涵盖)。最终,通过更改适当资源的请求以包含每个条目的“变量”(正是我所需要的),或多或少地重新实现了我以前在插件系统中进行Loader尝试的功能。但是,令人遗憾的是,我遇到了与Loader相同的障碍-文件(和我的代码)只能访问一次。

我还尝试了“从外到内”-查看生成的块,其中每个条目在树中都有HBS文件的模块,但是这些模块已经过处理和编译,这似乎并不意味着成功。

source

最后,与常规插件类似,我决定尝试使用解析插件。我一直在想:“我只需要这些NormalModuleReplacementPlugin调用即可解决其他问题,这不难!”

但是那还行不通,存在同样的“钩子每个文件仅被调用一次”的问题,现在我什至无法从所需文件中获取入口点,因为它们甚至还没有得到适当解决。 / p>

TL; DR

因此,如果我可以让我的插件或加载程序告诉Webpack“嘿,下一次我NormalModuleFactory时该文件将有所不同,请再次检查”,我认为这将解决所有问题并使所有工作正常我想要的方式。

如果这不可能,那么我可能只会恢复到顺序构建:

  1. 使用require解析为require的{​​{1}}
  2. 使用entry1.js解析为*.hbs的{​​{1}}

以及刻录时间和RAM。但是你能做什么。

感谢您阅读。

1 个答案:

答案 0 :(得分:-1)

我有同样的问题。唯一帮助我的是Webpack Virtual Modules。我根据某些模板动态生成了入口模块的多个实例。因此,这些模块具有不同的ID,并且在条目之间不共享。