检查 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 有这样的东西吗?

编辑澄清:

如果我一直都需要ProfileHelperFeedHelper,那么其中一个模块将不会被使用。在任何给定页面上最多加载其中一个。在个人资料页面上,加载了 ProfileHelper,但未加载 FeedHelper。 Feed 页面反之亦然。

另外,我不想使用require.ensure,因为它是异步的。

【问题讨论】:

如果您的问题是:webpack 是否对所需模块进行重复数据删除?是的。 我的问题是只有在已经下载的情况下我才需要一些东西。 也许你真正需要的是代码拆分。 webpack.github.io/docs/code-splitting.html require.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 中是不是已加载模块?的主要内容,如果未能解决你的问题,请参考以下文章

webpack 是什么

webpack 是什么

webpack入坑之旅扬帆起航

webpack在PC项目中的应用

使用 webpack 配置 CSS 模块时出错

webpack01