Output require() construct with AMD generation - requirejs

I currently have a set of RequireJs modules defined as:
require(['dep1', 'dep2'], function(dep2, dep2) {
...
});
I'm looking to convert these into TypeScript modules, however the AMD generation outputs them with the define() construct:
define(['dep1', 'dep2'], function(dep2, dep2) {
...
});
I can see how they would essentially be equivalent. However I have always worked on the following basis:
Define: When you want to be able to pass the module into other modules.
Require: When the module just needs to be executed
Are these assumptions redundant? Or is there a way to instruct TypeScript to output the require() construct for a module?

Are these assumptions redundant?
Yes. require should only be used when you want to lazy load.
is there a way to instruct TypeScript to output the require() construct for a module
Yes. Use the requirejs definition : https://github.com/borisyankov/DefinitelyTyped/blob/master/requirejs/require.d.ts and write code to call the require function manually.

You can write one file manually using require() to load other modules or use the data-main property on the element loading require.js.

Related

How can I load a global script (<script src="">) in Jest

I need to make a JavaScript script available as a global script tag for a unit test in Jest.
I understand that Jest uses jsdom and in jsdom there is an api that allows to initialize the DOM and load script but I cannot seem to find a way on how to do this in Jest?
If you do not need to test the script itself, which, given the fact it is an external library, you shouldn't, you can mock it globally.
First of all you need to setup a jest setupFile, this file will be executed before test execution and the mocks available there should remain available for each test file, to do so write something like this in package.json or, better, in jest.config.js
"jest": {
"setupFiles": [
"<rootDir>/jest/globals.js"
]
}
Then create that file and write your global mocks there.
Now you will say "'Duh'? How do I mock the external library imported through the tag script?" Well, what I found useful for this and a number of other reason is to wrap the imported library in a separate module, this way you can use the wrapper throughout your code instead of using directly the globally imported external library, which will give you the possibility to mock the said module globally and voilà, it is done!
You can simply use require to load your script.
However, keep in mind that the script must be saved locally.
require('relative/path/to/your/script')
Some more interesting information here :
https://info343.github.io/jest.html

Typescript module import with configuration file

I would to like forge the path to access node_modules with some configuration file. It seems it's not possible to do the thing below, how should I forge my path then?
The aim is to write absolute path to some node_modules ( cause some files are splitted so this is needed).
import someFileSettings from "./../../models/someFileSettings";
import * as request from JSON.stringify(someFileSettings .somePathIneed+"request");
No, it's not possible, because TypeScript modules follow the standard ES6 modules. To do that, there is a module loader API, based on promises.
Here is the explanation from the book of Dr. Axel Rauschmayer:
16.9.1 Can I use a variable to specify from which module I want to import?
The import statement is completely static: its module specifier is always fixed. If you want to dynamically determine what module to load, you need to use the programmatic loader API:
const moduleSpecifier = 'module_' + Math.random();
System.import(moduleSpecifier)
.then(the_module => {
// Use the_module
})
... but, notice this warning:
The module loader API is not part of the ES6 standard

RequireJS - When specify module id in define()

In RequireJS documents (http://requirejs.org/docs/api.html#modulename), I couldn't understand this sentence.
You can explicitly name modules yourself, but it makes the modules less portable
My question is
Why explicitly naming module makes less portable?
When explicitly naming module needed?
Why explicitly naming module makes less portable?
If you do not give the module a name explicitly, RequireJS is free to name it whichever way it wants, which gives you more freedom regarding the name you can use to refer to the module. Let's say you have a module the file bar.js. You could give RequireJS this path:
paths: {
"foo": "bar"
}
And you could load the module under the name "foo". If you had given a name to the module in the define call, then you'd be forced to use that name. An excellent example of this problem is with jQuery. It so happens that the jQuery developers have decided (for no good reason I can discern) to hardcode the module name "jquery" in the code of jQuery. Once in a while someone comes on SO complaining that their code won't work and their paths has this:
paths: {
jQuery: "path/to/jquery"
}
This does not work because of the hardcoded name. The paths configuration has to use the name "jquery", all lower case. (A map configuration can be used to map "jquery" to "jQuery".)
When explicitly naming module needed?
It is needed when there is no other way to name the module. A good example is r.js when it concatenates multiple modules together into one file. If the modules were not named during concatenation, there would be no way to refer to them. So r.js adds explicit names to all the modules it concatenates (unless you tell it not to do it or unless the module is already named).
Sometimes I use explicit naming for what I call "glue" or "utility" modules. For instance, suppose that jQuery is already loaded through a script element before RequireJS but I also want my RequireJS modules to be able to require the module jquery to access jQuery rather than rely on the global $. If I ever want to run my code in a context where there is no global jQuery to get, then I don't have to modify it for this situation. I might have a main file like this:
define('jquery', function () {
return $;
});
require.config({ ... });
The jquery module is there only to satisfy modules that need jQuery. There's nothing gained by putting it into a separate file, and to be referred to properly, it has to be named explicitly.
Here's why named modules are less portable, from Sitepen's "AMD, The Definite Source":
AMD is also “anonymous”, meaning that the module does not have to hard-code any references to its own path, the module name relies solely on its file name and directory path, greatly easing any refactoring efforts.
http://www.sitepen.com/blog/2012/06/25/amd-the-definitive-source/
And from Addy Osmani's "Writing modular javascript":
When working with anonymous modules, the idea of a module's identity is DRY, making it trivial to avoid duplication of filenames and code. Because the code is more portable, it can be easily moved to other locations (or around the file-system) without needing to alter the code itself or change its ID. The module_id is equivalent to folder paths in simple packages and when not used in packages. Developers can also run the same code on multiple environments just by using an AMD optimizer that works with a CommonJS environment such as r.js.
http://addyosmani.com/writing-modular-js/
Why one would need a explicitly named module, again from Addy Osmani's "Writing modular javascript":
The module_id is an optional argument which is typically only required when non-AMD concatenation tools are being used (there may be some other edge cases where it's useful too).

Can alternative AMD loaders be used in functional testing with intern?

The useLoader configuration for specifying another AMD loader to use does not seem to be used in functional test modules.
I want to load a JSON file into a javascript object to use in my functional test suite by using a requireJS JSON plugin (https://gist.github.com/millermedeiros/1255010) but it does not work due to what I assume is the plugin looking for requireJS specific constructs:
TypeError: Cannot read property 'isBuild' of undefined
at Object.load </home/dev/public_html/gold_widgets_15644/web/assets/js/json.js:27:24>
at injectPlugin <node_modules/intern/node_modules/dojo/dojo.js:608:12>
at <node_modules/intern/node_modules/dojo/dojo.js:543:7>
at Array.forEach <native>
at forEach <node_modules/intern/node_modules/dojo/dojo.js:220:19>
at execModule <node_modules/intern/node_modules/dojo/dojo.js:535:5>
at <node_modules/intern/node_modules/dojo/dojo.js:582:7>
at guardCheckComplete <node_modules/intern/node_modules/dojo/dojo.js:566:4>
at checkComplete <node_modules/intern/node_modules/dojo/dojo.js:574:27>
at onLoadCallback <node_modules/intern/node_modules/dojo/dojo.js:656:7>
What's the best way to include json from a file in a functional testing module if alternative AMD module loaders such as requireJS are not supported in functional tests?
Should one just use node's fs library in conjunction with JSON.parse?
You're correct, functional tests run with the default loader. A functional test just drives the browser -- it doesn't run in the same environment as the application under test.
You can use both AMD and CommonJS libraries in your functional tests. For example, you can install the Dojo npm module and add it to the packages list in your test config to use dojo/text (and any other Dojo utility functions). You can also load Node's fs module using the dojo/node module included with Intern, like:
define([ 'intern/dojo/node!fs', ... ], function (fs, ...) {
...
});

Is there any way to define global dependencies in Require.js?

Backstory:
I've currently got a Require.js and jQuery/Backbone.js using site. Until now, jQuery and Backbone have stayed outside of Require, letting me do:
define([], function() {
// NOTE: Using Backbone and $ without an import!
new Backbone.View(el: $('#foo');
});
That's worked really well: without that approach, just about every module in my site would have to add a Backbone/jQuery dependency.
But then the other day I needed to package up a portion of our code as an external library. I made a separate require config file for it, and everything seemed great, until I compiled ("optimized") all the files in to a single library file, and realized that Backbone/jQuery (and related plug-ins/libraries) weren't getting included.
So, I added a bunch of shims, and got Backbone, jQuery, and all the related libraries in to Require. However, I still have a ton of modules that expect $ and Backbone to just exist. That should be ok, because Backbone/jQuery both register their variables globally, but it's not because of Require's load order.
Basically, any module without dependencies is broken, because they load before Require loads the jQuery/Backbone shim. Any modules that have dependencies don't have this issue, because jQuery/Backbone have already been loaded by the time they get loaded.
It seems like my only option is to add an explicit Backbone/jQuery to every module without dependencies. I've got a bunch of modules like that though, and ideally I'd prefer not to have to import jQuery/Backbone anywhere.
Question
So, my question is: is there any way to tell Require "load these X modules/shims before you load everything else"? Or, to put it another way, is there any way to tell Require that all of my modules depend on certain other modules?
I thought putting Backbone at the top of my initial require:
require(['backbone', ...
but that didn't help; the other dependency-less modules still load before it.
I see no reason this would not work:
require(['backbone', 'jquery'], function () {
require(['main']);
});
The idea is to wrap what was your initial entry point to your application in a require call that loads Backbone and jQuery. If the modules of your application are loaded only because main is required (that is, if there is no require call elsewhere that loads any module needed by main), then with the code above both Backbone and jQuery are guaranteed to be loaded before any of the modules used by main are.

Resources