掌握Meteor中的外部脚本加载顺序(谷歌地图)

时间:2013-03-05 20:55:49

标签: javascript google-maps meteor

我尝试将google地图(外部加载的脚本)添加到流星应用程序中失败,我注意到有两种问题:

  1. 如果我做了简单的事情并将主API脚本添加到我的<head></head>,那么它会被渲染为最后
  2. 当发生这种情况时,我不得不在主API脚本之后在我的模板的<head>中再次插入任何依赖的脚本。 (否则脚本抱怨他们没有看到API blabla ..)
  3. 然后实际函数调用的时间到了 - 现在将其放在<head>之后其余部分将无效。您需要使用Template.MyTemplate.rendered。
  4. 基本上我的问题是:

    • 处理这类事情的最简洁方法是什么?
    • 我可以使用其他一些变量/方法来确保我的HTML主要API文件首先在我的HTML中调用吗?

3 个答案:

答案 0 :(得分:7)

我刚刚发布了一个关于氛围(https://atmosphere.meteor.com)的软件包,可能会有所帮助。它被称为session-extras,它定义了一些我用来帮助集成外部脚本的函数。代码在这里:https://github.com/belisarius222/meteor-session-extras

基本思想是异步加载脚本,然后在脚本加载完成后的回调中设置Session变量。我使用session-extras包中的函数来尝试使这个过程更平滑。我有一些函数有3或4个不同的依赖项(脚本和订阅),所以它开始变得毛茸茸......

我想我应该补充一点,然后你可以根据是否存在所有依赖项来有条件地渲染模板。因此,如果你有一个facebook按钮,例如,有帮助器检查Session变量,你可以给它一个“禁用”的css类并显示“加载facebook ...”,直到所有必要的脚本都已加载。

编辑2013年3月14日

在许多情况下,还有一种完全不同的方法:创建自己的包。目前Meteorite (instructions)可以实现这一功能,Meteor本身很快就可以使用该功能。这种方法的一些例子是:

如果您将js文件放在一个包中,它会在您的应用代码之前加载,这通常是包含库的好方法。制作包的另一个好处是包可以相互声明依赖关系,所以如果有问题的脚本是例如jQuery插件,你可以在包的package.js文件中指定包依赖于jQuery,这将确保正确的加载顺序。

有时它会变得更有趣(在中文诅咒意义上),因为许多外部服务,包括mixpanel和filepicker.io,都有两部分加载过程:1)一个JS片段包含在最后正文,以及2)由该片段异步加载的CDN更大的脚本。 js代码片段通常(但不总是!)在更大的脚本加载之前使一些方法可用,这样您就可以调用其函数而无需设置更多逻辑来确定其负载状态。 Mixpanel这样做,虽然重要的是要记住,来自外部服务的一些JS片段希望你在代码片段的末尾设置API密钥,保证在更大的脚本加载之前;在某些情况下,如果在设置API密钥之前加载脚本,则库将无法正常运行。有关尝试解决方法的示例,请参阅meteor-mixpanel软件包。

可以从CDN自己下载更大的js文件并将其粘贴在您的应用程序中;但是,有充分的理由不这样做: 1)托管代码可能会更改,除非您虔诚地检查它,否则您的代码可能会过时并开始使用旧版本的API 2)这些库通常已经过优化,可以快速加载代码段,不会显着增加页面加载时间。如果您在应用程序中包含较大的JS文件,那么您的服务器必须提供服务,而不是CDN,并且它将在初始页面加载时提供服务。

答案 1 :(得分:2)

听起来您正在通过将其与模板中的HTML链接来加载Javascript文件。有一种更流星的做法:

来自Meteor Docs

  

Meteor收集树中的所有JavaScript文件,但不包括   客户端的服务器和公共子目录。它缩小了这一点   捆绑并将其提供给每个新客户。你可以自由使用一个   整个应用程序的JavaScript文件,或创建嵌套树   单独的文件,或介于两者之间的任何内容。

所以考虑到这一点,不要将gmaps.js链接到头部,只需下载未缩小版本的gmaps并将其放入应用程序的树中。

同样来自Meteor Docs:

  

最好以这样的方式编写应用程序   对文件加载顺序不敏感,例如   使用Meteor.startup,或将加载顺序敏感代码移入   智能包,可以明确控制两个的加载顺序   他们的内容和他们的负载顺序相对于其他包。   但是,有时您的应用程序中的加载顺序依赖性   不可避免的。加载应用程序中的JavaScript和CSS文件   根据这些规则:

     

加载应用程序根目录下的lib目录中的文件   第一    [强调添加]

如果序列仍然存在问题,请将js文件放入client/lib,它将在您编写的所有Javascript之前加载。

答案 2 :(得分:1)

我使用了meteor-external-file-loader和一些异步循环来加载一些脚本,这些脚本将按照你指定的顺序加载javascript(或样式表)。

确保有陨石并添加上面的包&gt;&gt; mrt add external-file-loader

这是我为了使用这个包而编写的函数:

var loadFiles = function(files, callback) {
  if (!callback) callback = function() {};

  (function step(files, timeout, callback) {
    if (!files.length) return callback();

    var loader;
    var file = files.shift();
    var extension = file.split(".").pop();
    if (extension === "js")
      loader = Meteor.Loader.loadJs(file, function() {}, timeout);
    else if (extension === "css") {
      Meteor.Loader.loadCss(file);
      loader = $.Deferred().resolve();
    }
    else {
      return step(files, timeout, callback);
    }

    loader.done(function() {
      console.log("Loaded: " + file);
      step(files, timeout, callback);
    }).fail(function() {
      console.error("Failed to load: " + file);
      step(files, timeout, callback);
    });
  })(files, 5000, callback);
}

然后使用它,添加一个为模板创建的方法,如下所示:

Template.yourpage.created = function() {
  var files = [
    "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js",
    "javascripts/bootstrap.min.js"
  ];

  loadFiles(files, function() {
    console.log("Scripts loaded!");
  });
}

快速编辑:发现将.created方法的功能放在Meteor.startup()中的/ lib文件夹中是个好主意。

Meteor.startup(function() {
  if (Meteor.isClient) {
    // Load files here.
  }
});
警告:很多javascript文件=真正很长的加载时间....不确定这将受到正常的流星javascript文件以及那里的加载顺序的影响。我会确保在用户对网站采取行动之前没有冲突(或者如果存在,则首先加载它们)。