这里有一个很长的。尽管我对答案或解决方案没有太多(或任何)期望,但仍然感觉像乐趣 分享/发泄的有趣问题。
我有一个有 2 个入口点的应用程序。它们都导入了相同的文件,main.ts而后者又导入了一个 Handlebars 模板main.hbs:
entry1.ts
? main.ts
? main.hbs
? …
entry2.ts
? main.ts
? main.hbs
? …
Run Code Online (Sandbox Code Playgroud)
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.hbsmain.v1.hbs
main.ts进口menu.ts实际上负载menu.v1.hbsentry2.ts导入实际加载的main.ts导入main.hbsmain.v2.hbs
main.ts进口menu.ts实际上负载menu.v2.hbs我认为这种方法会给我带来多种优势:
不必更改所需文件(实际上是数百个)中的源代码。
如果我不关心这一点,我可以使用带有表达式的require,然后使用摇树来只留下每个条目中使用的模板。然而…
require()语法而不适用于 ES 风格的静态import——所以不向前兼容可以在“重定向”之前检查变体文件是否存在,如果不存在则回退到默认文件。
重要的是,这允许我逐步进行此转换,因为创建了更多新“v2”变体的文件,而无需保留哪些导入映射到哪些文件或其他内容的静态列表。
也许可以在单个编译运行中完成此转换。
如果我不关心这个,我可以单独编译每个条目,在每次运行时设置适当的选项。然而,应用程序相当大,需要几分钟的时间来构建,甚至需要增加节点内存限制。因此,按顺序或并行单独构建每个条目并不太好,尽管如果没有其他方法,这是我的最后手段。无论如何,鉴于 Webpack 的功能,我觉得这是我应该能够在单个构建中完成的事情。
这是一个内置于 Webpack 的插件,乍一看似乎满足了我的需求:拦截require对特定模块的调用并将它们更改为其他模块,它甚至还支持正则表达式和谓词函数。但是我很快放弃了这个,因为在编译过程中映射不能改变。这意味着我不能为每个条目设置不同的替换规则。
现在我们深陷战壕。我想,为什么不编写自己的加载程序来解决这个问题?加载程序能够读取其根条目,因此理论上我应该能够使用该信息来代替main.hbs加载main.v1.hbsforentry1和main.v2.hbsfor entry2。
虽然最初这似乎有效(尽管我讨厌这种方法的非无状态性),但我发现 Webpack 似乎在第一次执行它时缓存了 require/resolution:while processing main.ts. 因此,即使使用我拥有的所有逻辑,我的加载器每个文件只调用一次,而不是每个调用一次require,我无法实现我想要的。
我研究了告诉 Webpack“不要缓存它,下次再读一遍”的方法,但我没有运气。由于这两个条目进口main.ts其进口main.hbs只有一次,治疗的WebPack既TS和HBS为每个只有1模块,不管事实,他们被导入到多个项文件。我想这是一个必不可少的优化,但对于这种特定情况,我没有找到解决方法。
由于 Loader 没有得到我需要的东西,我尝试编写一个插件。我浏览了详细的文档并尝试连接到compiler和compilation但并没有走得太远。我查看了NormalModuleReplacementPlugin的源代码并NormalModuleFactory以相同的方式使用(文档似乎没有涵盖它)。最终通过更改适当资源的请求以包含每个条目的“变体”,或多或少地重新实现了我之前在插件系统中尝试加载器的功能——正是我需要的。然而,遗憾的是,我遇到了与 Loader 相同的障碍——文件(和我的代码)只被访问一次。
我还尝试“从外到内”——查看结果块,其中每个条目在其树中都有 HBS 文件的模块,但这些模块已经过处理和编译,这似乎不是通往成功的道路。
最后,与常规插件类似,我决定尝试使用解析插件。我一直在想,“我只需require要将这些调用解析到其他地方,这应该不难!”
但这并没有奏效,有相同的“每个文件只调用一次钩子”问题,现在我什至无法从所需文件中获得入口点,因为它们甚至还没有得到正确解决。
因此,如果我能让我的插件或加载程序告诉 Webpack“嘿,这个文件下次我require时会有所不同,所以请再次检查它”,我认为这可以解决所有问题并使一切按照我想要的方式工作。
如果这是不可能的,那么我可能只会恢复到顺序构建:
entry1.js与*.hbs解析为*.v1.hbsentry2.js与*.hbs解析为*.v2.hbs并燃烧时间和内存。但你能做什么呢。
感谢您的阅读。
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |