检查 Webpack 中是不是已加载模块?
Posted
技术标签:
【中文标题】检查 Webpack 中是不是已加载模块?【英文标题】:Checking if a module is already loaded in Webpack?检查 Webpack 中是否已加载模块? 【发布时间】:2017-04-24 08:29:45 【问题描述】:我在一家拥有自定义 JS 模块捆绑器的公司工作。该实现有一个函数requireIfLoaded
,它允许您要求一个模块,但前提是它已经被加载。如果模块尚未加载,则会引发错误。使用 requireIfLoaded
不会捆绑模块。这大大减少了我们的文件大小。
这是一个有用的例子:
if (page === PROFILE)
// ProfileHelper should already be downloaded if we're on the profile page.
const ProfileHelper = requireIfLoaded('ProfileHelper');
ProfileHelper.doSomething();
else if (page === FEED)
// FeedHelper should already be downloaded if we're on the feed page.
const FeedHelper = requireIfLoaded('FeedHelper');
FeedHelper.doSomething();
为个人资料页面和供稿页面生成单独的捆绑包。 require('ProfileHelper')
未在提要页面代码路径中调用,因此 ProfileHelper
未包含在提要包中。 require('FeedHelper')
不会在配置文件页面代码路径中调用,因此FeedHelper
不包含在配置文件包中。 Webpack 有这样的东西吗?
编辑澄清:
如果我一直都需要ProfileHelper
和FeedHelper
,那么其中一个模块将不会被使用。在任何给定页面上最多加载其中一个。在个人资料页面上,加载了 ProfileHelper
,但未加载 FeedHelper
。 Feed 页面反之亦然。
另外,我不想使用require.ensure
,因为它是异步的。
【问题讨论】:
如果您的问题是:webpack 是否对所需模块进行重复数据删除?是的。 我的问题是只有在已经下载的情况下我才需要一些东西。 也许你真正需要的是代码拆分。 webpack.github.io/docs/code-splitting.htmlrequire.ensure
总是需要模块,我只想在文件已经下载的情况下才需要文件。此外,require.ensure
是异步的。我想同步检查是否已经需要给定的模块。
@LeoJiang,你只需要在你真正需要模块(异步)时为特定模块调用require.ensure
,并将你的逻辑更改为始终以异步方式工作。不支持检查模块是否已加载的方法。我也没有真正了解您的用例。如果 ProfileHelper 尚未加载但您到达个人资料页面,您是否会出错?为什么不只是在您到达个人资料页面时异步获取 ProfileHelper?
【参考方案1】:
Webpack 将多次删除所有需要的模块,并且已经加载的模块将不会再次初始化(遵循 CommonJS 规范)。因此,基本上,只需直接要求所有依赖项即可!
更重要的是:如果您使用 webpack,请不要包装您的需求。确定您实际使用的模块的静态分析将停止正常工作,并且 webpack 会捆绑太多。
【讨论】:
自 v2 以来的 Webpack 也将仅包含那些使用的依赖项。因此,在捆绑过程中根据需要使用 required 它只会包含一次。 澄清一下,这与重复数据删除无关。 @MichałIgnaszewski 使用所有依赖项,但并非一直使用。 IE。整个文件加载到多个页面上,但这些页面并未使用所有代码路径。依赖项适用于某些代码路径。【参考方案2】:这种方法与使用 webpack 捆绑是对立的。
require 语句正是指示 webpack 编译什么的东西。它永远不会编译您的条件需求,因为它们将在运行时进行评估(但 webpack 包是预编译的)并且 webpack 不会将它们中的任何一个添加到您的包中。
您正在寻找的是代码拆分:https://webpack.js.org/guides/code-splitting-require/
教程:
http://jonathancreamer.com/advanced-webpack-part-2-code-splitting/ https://formidable.com/open-source/playbook/docs/frontend/webpack-code-splitting/【讨论】:
我所在的公司为不同的页面生成了许多不同的捆绑包。大多数模块不必检查它需要在哪个包中,它们只需检查已经需要哪些模块。代码拆分增加网络请求,我想要的不需要额外的网络请求。【参考方案3】:从您的问题和您的 cmets 看来,ProfileHelper
似乎是通过单独的 <script>
标记加载的,并且可以在 window
范围内立即使用,无需进一步异步加载。
此外,这个助手似乎不是由requireIfLoaded
管理的,如果它们尚未加载,它将抛出。
所以,在这些假设下,requireIfLoaded
的作用只是检查模块在window
下是否可用,如果不可用则抛出错误。
那么...为什么不创建自己的requireIfLoaded
?
function requireIfLoaded(file)
let m = window[file];
if(m)
return m;
else
throw new Error(`Cannot find module '$file'`)
我错过了什么吗?
【讨论】:
【参考方案4】:我找到了解释这一点的文档。它说 “尽管有各种加载 javascript 的选项,但仍然无法下载 JavaScript 文件并将其设置为在任意时间执行。你可以说立即执行,也可以推迟到 DOM 文档完成,但你可以” t 指定任何其他时间点来执行代码。"
更多信息Seperating javascript download and installation
【讨论】:
以上是关于检查 Webpack 中是不是已加载模块?的主要内容,如果未能解决你的问题,请参考以下文章