在我提到文件名之前,requirejs怎么知道加载一个必需的js文件? [英] how does requirejs know to load a required js file before I ever mention the file name?

查看:100
本文介绍了在我提到文件名之前,requirejs怎么知道加载一个必需的js文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找@ Domenic使用requirejs的简单示例,从这个答案:
使用require.js的简单示例
我在这里包括。

I am looking @Domenic's simple example of using requirejs, from this answer: simple example for using require.js which I am including here.

shirt.js:

shirt.js:

define({
    color: "black",
    size : "large"
});

logger.js:

logger.js:

define(function (require) {
    var shirt = require("./shirt");

    return {
        logTheShirt: function () {
            console.log("color: " + shirt.color + ", size: " + shirt.size);
        }
    };
});

main.js:

main.js:

define(function (require) {
    var shirt = require("./shirt");
    var logger = require("./logger");

    alert("Shirt color is: " + shirt.color);
    logger.logTheShirt();
});

main.html:

main.html:

<script data-main="../js/main" src="../js/require.js"></script>

有一些非常奇怪的事情:
点shirt.color 用于main.js,
shirt.js和logger.js刚安排加载,异步(我猜),
so shirt.js还没有被阅读过。我假设加载是异步的原因是我的印象是同步加载在chrome中的javascript中几乎被禁止(XMLHttpRequest仍然有一个同步的选项,但如果使用,它会在chrome控制台上发出警告主线程上的同步XMLHttpRequest因其对最终用户体验的不利影响而被弃用。)。

There's something very strange going on: at the point where shirt.color is used in main.js, shirt.js and logger.js have just been scheduled to be loaded, asynchonously (I presume), so shirt.js hasn't actually been read yet. The reason I presume the loading is asynchronous is that my impression is that synchronous loading has been pretty much outlawed in javascript in chrome (XMLHttpRequest still has an option to be synchronous, but if used, it warns on the chrome console Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.).

然而,这个小应用程序似乎工作,可靠。
如果我用一个引用世界其他
方面资源的网址替换./ shirt.js,它甚至可以正常工作,并在加载html页面之前清除浏览器缓存。

And yet, this little app seems to work, reliably. It even works reliably if I replace "./shirt.js" by a url referring to a resource on the other side of the world, and I clear my browser cache before loading the html page.

这怎么可能?

如果我看看chrome dev控制台中的时间,看起来耗时的shirt.js加载了
实际上发生了之前请求它甚至启动的函数。
I.e.不知何故,它知道在程序中的任何内容之前加载shirt.js,根本就是./shirt。

If I look at timings in chrome dev console, it appears that the time-consuming shirt.js load actually happened before the function that requested it even started. I.e. somehow it knew to load shirt.js before anything in the program referred to "./shirt" at all.

看来这里有一些非常鬼鬼祟祟的魔法。
所以我很想知道:

It seems there is some very sneaky magic going on here. So I'm interested to know:


  1. 在遇到任何要求之前,requirejs是如何知道加载shirt.js的? / li>
  2. 在多大程度上可以依赖它?

  3. 如何修改这个例子以避免依赖偷偷摸摸的魔法?

  4. 对于我们这些不信任偷偷摸摸的魔法的人,有没有办法在使用requirejs时禁用它?


推荐答案


在遇到任何要求之前,requirejs是如何知道加载shirt.js的?

how did requirejs know to load shirt.js before anything asked for it?

这是你的模块:

define(function (require) {
    var shirt = require("./shirt");
    var logger = require("./logger");

    alert("Shirt color is: " + shirt.color);
    logger.logTheShirt();
});

当调用 define 时,RequireJS检测到它被称为没有依赖列表。所以它扫描你为 require 调用的实例传递的回调,它接受一个字符串文字的参数,然后它抓取单个参数并列出这些参数的列表它作为模块的依赖列表。你的模块在功能上等同于:

When define is called, RequireJS detects that it was called without a dependency list. So it scans the callback you pass for instances of the require call taking a single argument which is a string literal, and it grabs the single argument and makes a list of these arguments that it takes as the dependency list of the module. Your module becomes functionally equivalent to this:

define(["require", "./shirt", "./logger"], function (require) {
    var shirt = require("./shirt");
    var logger = require("./logger");

    alert("Shirt color is: " + shirt.color);
    logger.logTheShirt();
});

所以 ./ shirt 和<$ c在实际调用回调之前加载$ c> ./ logger 。然后当执行 require(./ shirt) require(./ logger)时,它们是只需在已加载模块的地图中查找。 (并且,因此,在传递给 require 可以工作> define 。否则,你会得到可怕的模块尚未加载但对于上下文错误。)

So ./shirt and ./logger are loaded before the callback is actually called. Then when require("./shirt") and require("./logger") are executed, they are just lookups in a map of already loaded modules. (And, because of this, calls to require with a single string argument can only work when called in a callback passed to define. Otherwise, you get the dreaded "Module has not been loaded yet for context" error.)

此功能称为CommonJS糖,因为需要调用使用单个参数作为字符串并返回模块是CommonJS本身支持的。原生AMD require 调用将一系列依赖项作为第一个参数和一个可解决的模块传递给它的可选回调。

This capability is called the "CommonJS sugar" because a require call that uses a single parameter which is a string and returns a module is what CommonJS supports natively. The native AMD require call takes an array of dependencies as the first argument and an optional callback to which the resolved modules are passed.


在多大程度上可以依赖它?

to what extent can this be relied on?

我依赖于CommonJS数百个模块的糖没有问题。

I've relied on the CommonJS sugar for hundred of modules without problem.

这种模式的一个限制是如果你尝试将除字符串文字之外的东西传递给 require 。例如,如果你这样做:

The one limitation to this pattern is if you try to pass something else than a string literal to require. For instance if you do this:

define(function (require) {
    var shirtName = "./shirt";
    var shirt = require(shirtName);

这将甩掉RequireJS。它赢了检测到你的模块需要 ./ shirt 模块,你会得到我上面提到的错误。

This will throw off RequireJS. It won't detect that your module needs the ./shirt module and you'll get the error I mentioned above.


如何修改这个例子以避免依赖偷偷摸摸的魔法?

how would one modify this example to avoid relying on the sneaky magic?



define(["./shirt", "./logger"], function (shirt, logger) {
    alert("Shirt color is: " + shirt.color);
    logger.logTheShirt();
});




我们不信任偷偷摸摸的魔法,有没有办法在使用requirejs时禁用它?

for those of us who don't trust sneaky magic, is there a way to disable it when using requirejs?

没有你可以使用的旗帜防止RequireJS支持CommonJS糖。如果你想避免在你自己的代码中依赖它,你可以编码你的mo像我在前面的片段中所示的dules:调用 define ,将依赖列表作为第一个参数,并将模块作为回调的参数。

There's no flag you can use to prevent RequireJS from supporting the CommonJS sugar. If you want to avoid relying on it in your own code, you can code your modules like I've shown in the previous snippet: call define with a list of dependencies as the first argument, and get the modules as arguments of your callback.

这就是说,我认为没有充分理由这样做。我已经使用了RequireJS多年,如果有的话,我一直在使用定义的代码,其中依赖于依赖于CommonJS糖的代码的依赖列表。我发现后者在各种开发工具中效果更好。

This being said, I see no good reason to do that. I've used RequireJS for years and if anything I've been moving code that uses define with a list of dependencies to code that relies on the CommonJS sugar. I find that the latter works better with various development tools.

这篇关于在我提到文件名之前,requirejs怎么知道加载一个必需的js文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆