我正在将一个旧的应用程序转换到Webpack,我使用的是Webpack5.56(撰写本文时最新的版本)。
我的应用程序是本地化的,我有一个文件夹,里面有一些区域设置文件,
locales
- locale.en.ts
- locale.de.ts
- etc
这些locale文件中的每一个都是一个ES模块,它们都导出(不同的实现)相同的函数-getText
、printNumber
等。我有一个 Package 器模块,它动态地为当前用户提供正确的locale:
// localization.ts
interface LocaleModule {
getText(text: string): string;
// etc
}
let module: LocaleModule;
import(`locales/locale.${currentUser.language}`).then(m => {
module = m;
});
export function getText(text: string): string {
return module.getText(text);
}
当页面呈现时,我知道当前用户的语言。我希望包含正确的locale.*.js
脚本作为初始块,以便:
- 浏览器在开始下载locale文件之前不必等待主块加载。
localization.ts
中的函数可以是同步的。
这看起来很适合webpackMode: "weak"
,因为如果locale
文件由于任何原因丢失,我希望在控制台中得到一个错误(而不是默默地降低性能)。
当所需的块总是在初始请求(嵌入在页面中)中手动提供时,这对于通用呈现非常有用。
下面是我的代码:
let module: LocaleModule;
import(
/* webpackMode: "weak" */
/* webpackChunkName: "locales/[request]" */
`./locales/locale.${currentUser.language}`
).then(m => {
module = m;
});
然而,似乎webpackMode: "weak"
导致Webpack根本不为引用的模块发出任何块。Webpack的输出文件夹中没有任何locale
文件。如果从来没有发出块,我就不能很好地在HTML中包含它!
这种行为的原因是什么?有没有一种干净的方法可以让Webpack为动态import
ed模块发出块,但不异步下载它们?(我知道我可以使用webpackMode: "lazy"
,并且只在脚本标记中包含块,但是如果缺少locale文件,我希望得到一个错误。)或者我有一个XY problem,还有我不知道的更好的方法吗
3条答案
按热度按时间3npbholx1#
我有类似的问题,并解决了这个问题。
我的本地文件如下所示:
我的语言环境结构如下所示:enter image description here
必须在Webpack配置中为
splitChunks.cacheGroups
添加新的cacheGroup
现在你所有的语言环境文件将被提取到另一个块文件中。
您可以使用任何处理程序来加载语言环境,例如:
为了让一切正常运转,你必须
总计:
ryevplcw2#
我不能发表这么长的评论,所以它必须是一个答案...
所以看起来模块之间没有真实的的链接,捆绑器不能在编译时解析它们,所以它们没有被发出。我在代码中唯一改变的是模块是如何导入的,它是开箱即用的:
我知道开关的情况并不理想,但捆绑器不能自动猜测这种模式:
./locales/locale.${langCode}.js
并添加目录中与.js
匹配的所有文件。doc表示以下内容:
“弱”:如果模块函数已经以其他方式加载,则尝试加载模块(例如,另一个块导入了该模块,或者加载了包含该模块的脚本)。仍会返回Promise,但只有在块已在客户端上时才能成功解析。如果模块不可用,承诺被拒绝。网络请求将永远不会被执行。当所需的块总是在初始请求中手动提供时,这对于通用呈现很有用(嵌入在页面中),但不适用于应用导航将触发最初未提供的导入的情况。
据我所知,这意味着块应该已经在页面上,并通过其他方式生成。
我希望这能帮助你解决你的问题。
64jmpszr3#
为了使用
weak
,你必须已经手动提供了文档中所述的块。这意味着将其作为注解添加到动态导入中不会创建任何块(与lazy
和lazy-once
相反)。有没有一种干净的方法可以让Webpack为动态导入的模块发出块,但不异步下载它们?
您可以:
1.使用
webpackMode: "lazy"
并按照您的说明在脚本标记中包含块(如果缺少块,则拒绝返回的Promise
)。1.您可以将locale js文件定义为dynamic entry points,然后自己手动加载它们。
对于您的示例,为每个语言环境创建一个入口点可能类似于:
这将发出
locale.de.js
和locale.en.js
包,然后您应该以某种方式手动加载<script defer src="locale.<locale>.js"></script>
,但这取决于您如何服务您的应用。您可以将
webpackMode: "lazy"
与webpackPreload: true
一起使用,以便解耦main
和locale
块请求。预加载的块开始与父块并行加载。