requirejs: What is the difference between these methods of establishing module requirements?

StackOverflow https://stackoverflow.com/questions/22396468

  •  14-06-2023
  •  | 
  •  

Вопрос

What is the difference between the following two methods of establishing dependencies, they seem to achieve the exact same results. For me it is allot easier to manage dependencies with #1:

//#1
define(function (require) {
    var $ = require('jquery');
    //$ is available here
});
//#2
define(['jquery'],function ($) {
    //$ is available here
});

Is there any disadvantage to using #1. I am having some difficulty with building modules that include it's dependencies in one file. Could using #1 have anything do do with that?

Here is that issue: requirejs: Build settings for a common.js module along with a main.js module where the result will be only two .js files served

Это было полезно?

Решение 2

The documentation at:

http://requirejs.org/docs/api.html#funcmodule

explains the biggest issue with first format -- it relies on Function::prototype::toString which is not 100% reliable.

EDIT

From the documentation:

This wrapper relies on Function.prototype.toString() to give a useful string value of the function contents. This does not work on some devices like the PS3 and some older Opera mobile browsers. Use the optimizer to pull out the dependencies in the array format for use on those devices.

Другие советы

The two formulations achieve the same result. Internally, RequireJS transforms the first formulation into this:

define(['jquery'], function (require) {
    var $ = require('jquery');
    //$ is available here
});

It scans the function for calls to require with a single string argument, gathers all the arguments and adds them to the list of dependencies passed to define. So it is a bit more computationally costly than the 2nd formulation, for two reasons. First, RequireJS has to use a regular expression to scan the function and find the calls to require. Second, when you load multiple modules like this, require has to be called multiple times. Compare a module that depends on 4 other modules and uses var x = require('x') to load them, after transformation:

define(['a', 'b', 'c', 'd'], function (require) {
    var a = require('a');
    var b = require('b');
    var c = require('c');
    var d = require('d');

    // Actual work.
});

And the same module written like this:

define(['a', 'b', 'c', 'd'], function (a, b, c, d) {
    // Actual work.
});

The first module needs to call require four times before getting to the actual work part. I would not lose sleep over the difference in performance but it exists.

Jeremy pointed out a limitation of the first formulation but elsewhere in the documentation, James Burke (author of RequireJS) gives a more detailed opinion about this possible issue:

Not all browsers give a usable Function.prototype.toString() results. As of October 2011, the PS 3 and older Opera Mobile browsers do not. Those browsers are more likely to need an optimized build of the modules for network/device limitations, so just do a build with an optimizer that knows how to convert these files to the normalized dependency array form, like the RequireJS optimizer.

Since the number of browsers that cannot support this toString() scanning is very small, it is safe to use this sugared forms for all your modules, particularly if you like to line up the dependency names with the variables that will hold their module values.

(Emphasis added.)

Someone who would think "Oh no! I'm going to have to use the optimizer" is not seeing the big picture. Chances are that the platforms where toString() is not available will need optimization anyway.

And to address your specific issue:

Could using #1 have anything do do with that?

In and of itself using the syntactic sugar in #1 won't make the optimizer fail to optimize your code. I have a >50-module project that mixes both styles. I did not have to do anything special to make r.js work.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top