Is XRegExp compatible with RequireJS? - javascript

I downloaded RequireJS single page app sample. In the www/lib folder, I put the XRegExp source xregexp-all.js (version 2.0.0).
In www/app/main.js, I added:
var xregexp = require('xregexp-all');
print(typeof(xregexp));
The console output is:
undefined
However, requireJS doesn't emit any error messages. Am I doing something wrong?

Yes, you are doing something wrong. Only some versions of the files distributed for XRegExp perform the required define call that defines them as RequireJS modules. The one you are using does not contain that call. You can determine this for yourself by searching for the define( string in the file.
You'll need to add a shim to your configuration so that RequireJS can load XRegExp or you'll have to use a version of the file that calls define, like for instance this one which is XRegExp 3.0.0 (still alpha). If you want to use 2.x then your config would be something like:
paths: {
xregexp: "../whatever/your/path/actualy/is/xregexp-all"
}
shim: {
xregexp: {
exports: "XRegExp",
},
}
Note that this config normalizes the module name to xregexp, so you would have to require it as xregexp, not xregexp-all. In general, I prefer not to have things like -all or .min in my module names since these may change depending on the situation.
The shim tells RequireJS that the value it should export when xregexp is required is that of the global symbol XRegExp. This is generally how you handle modules that are not AMD-aware.

A quick search for "amd", or "define" in a library's source code should be the quickest way to tell if it supports AMD scheme. If not, then it's not (doh!)
However, if the library exposes globals, then you can use RequireJS shim to load it up as well as path to tell RequireJS where to retrieve it.
// Exporting a traditional library through RequireJS
require.config({
paths : {
jaykweri : 'path/to/jQuery' // moduleName : pathToModule
},
shim : {
jaykweri : {exports : '$'} // exporting the global
}
});
// Using that library in requireJS
define(['jaykweri'],function(globl){
// globl === $
});

Related

How to use ES6-symbol polyfill

I have an Symbol is not defined in IE so I tried to use this library as polyfill
https://github.com/medikoo/es6-symbol
As inexperienced as I am, I do not really know how to include it so that it use as global.
In detail, in my code I include it using requirejs as:
requirejs.config({
paths:
{ 'symbol': 'libs/es6-symbol/index' }
})
//define it in app entry point
require([
'symbol'],
function (sy) {
//What should I do?
}
How should i approach this?
You cannot just load the index.js of es6-symbol with RequireJS. If you just look at it, you'll see:
'use strict';
module.exports = require('./is-implemented')() ? Symbol : require('./polyfill');
This is valid CommonJS code but not valid AMD code. RequireJS supports AMD natively, not CommonJS. To use CommonJS code with RequireJS you'd have at a minimum to wrap the code above in a define call, which means having a build step.
Ultimately, you should heed the advice of the README:
To port it to Browser or any other (non CJS) environment, use your favorite CJS bundler. No favorite yet? Try: Browserify, Webmake or Webpack
Research the bundlers, pick one, write a build configuration for it, and if you still have trouble you can ask on this site.

Using shim config with almond

I am trying to shim certain modules for usage with almond like so:
<script>
requirejs.config({
shim: {
'jQuery': { exports: 'jQuery' },
//etc.
</script>
as certain scripts will already be included. However, this code:
require(['jQuery', function($) {
});
results in "undefined missing jQuery". If I shim jQuery like this:
define('jQuery', function() {
return jQuery;
});
it works.
I am not building my JS at all, just dropping almond.js into an existing web software so I can develop my new components with AMD. I would like to shim existing globals for my new modules.
I am guessing shims are only resolved on build and that the build does exactly what I am doing above, is that correct?
The name for jQuery is hard-coded to "jquery". If you deviate from this you'll run into trouble. But that's not your only problem.
Using shim is not the same as calling define with a module name. When you use shim like you do in your question you tell the loader that there exist a module with the name jQuery and that once that module is loaded, RequireJS should return as a module value the value of the variable jQuery. The emphasized text is important: the loader will fetch and load a module named jQuery.
The define you show in your question would usually be placed together with the call to require.config, either just before it or just after it. This declares a module named jQuery. Because the module is already there, when the loader needs to get this module, there is nothing to fetch. This is an important difference when it comes to Almond.
Almond has restrictions, one of them is:
optimize all the modules into one file -- no dynamic code loading.
(Emphasis added.) Using the terms I've used in this answer this means "no fetching". When you use your define call, you are fine. When you use the shim, then unless you optimized your modules into one file, the loader has to try fetching the module. Almond cannot do that.

When adding AMD support to a library, should it also list its dependencies in define()

I am looking to add AMD support to a library although don't fully understand it. I have the following code that adds AMD support:
if (typeof define === "function" && define.amd) {
define(["imagesloaded", "hammer"], defineSequence);
} else {
sequence = defineSequence(imagesLoaded, Hammer);
}
The library depends on third-party libraries imagesLoaded and Hammer. I have listed them as dependencies in define() but I am concerned as to whether this limits a developer who uses my plugin to a specific file structure and naming convention whereby imagesloaded, hammer, and sequence all have to exist at the same directory level.
Is the above code correctly enabling AMD support and is this restriction to be expected?
Update: An example of my paths config as explained in the correct answer:
require.config({
baseUrl: 'scripts',
paths: {
imagesLoaded: 'imagesloaded.pkgd.min',
Hammer: 'hammer.min'
}
});
Path config can be used for defining the path to the dependencies. So you dont have to worry about users directory structure.
You should only provide information of what AMD module you are expecting as dependency and what functionality it should provide. It may even be abstract like $ (coming from jquery, zepto or sizzle)

Require.js 3rd Party Library Dependencies

What is the benefit of defining 3rd party libraries (JQuery/Underscore/Backbone) as modules and using those as dependencies?
require(["jquery", "underscore"], function($, _) {
// Use $ and _ in here
});
Underscore for example creates a global '_' variable, that I could just as easily use within the function above, assuming underscore is included prior to that function.
To be used by Require, Underscore requires the code to be modified to return a value, or a shim defined. Why bother, when I can just include it via a script tag?
I get that it provides a certain level of indirection and allows me to map other dependencies to those same variables, and have it scoped locally to that function. However, I don't see this ever being useful for these types of 3rd party libraries that form the core of the application.
After building some apps with Backbone/requireJs I can see no disadvantage in building a backbone app with requireJs, where the main dependencies are simple loaded via an old school script tag.
You have to load this requirements anyway in the first place, its used by the most of your modules and you will probably never exchange it with another framework. So there is no afford for the boilerplate code in every module.
You don't have to change the library to use it in AMD loader.
require.config({paths:{underscore:'//some.cdn/path/to/underscore.js'}})
require(["jquery", "underscore"], function($ /*, note that we don't override _ here */) {
// Use AMD $ and global _ in here
});

Import jQuery and other 3rd Party Libraries into TypeScript as modules using AMD

Question: Is there a way to import jquery into a TypeScript module using the AMD support (via the compiler) so it includes jquery as a dependency?
The key is to get the import statement, which makes the module a dependency in the define statement (see below).
define(["require", "exports", 'dataservice', 'jquery', 'knockout'],
function(require, exports, __ds__, $ , ko) {
...
}
)
Details:
I want to import jquery (and other 3rd party libraries) as a TypeScript modules with AMD. The goal is to make them appears as a dependency in the require list. However, the only way to make TypeScript to do this appears to be to have an import statement. And to have an import you need a module to import. But ... there is no jquery module to point to.
to.
Workarounds:
I can refer to the .d.ts and preload jquery in the main.js for require.js, but that means preloading all 3rd party libraries. Not terrible, but not ideal either as it doesnt take advantage of what we can already do with JavaScript and AMD.
I can create a module for each 3rd party library and wrap it, but then I get something like $.$. Which is even worse, IMO (and Irisk writing the wrong module code for each of these and getting out of synch).
So for now I am just preloading jquery in the main.js. but again, but this is less than ideal. Would have to do that for any library like knockout, backbone, etc that has no module.
Any better suggestions or something I am missing?
Update/Clarification:
I can also use shims in the config for dependencies amongst the libraries. But this still preloads the 3rd party ones. Example:
require.config({
baseUrl: '../',
paths: {
'jquery': 'lib/jquery-1.7.2',
'underscore': 'lib/underscore'
},
shim: {
jquery: {
exports: '$'
},
underscore: {
exports: '_'
}
}
});
One other work around would be use a type definition for requirejs and use your own require statements, rather than an import statement.
The downside to this is that the TypeScript import can be used with AMD or CommonJS with just a compiler change, so you would be marrying requirejs in your program more than you would be with an import.
There is an existing definition for requirejs on Definitely Typed.

Categories