Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mixin Underscore plugins in RequireJS?

What is the right way to execute code on Underscore when it gets loaded? I am trying to execute the below code to extend the _ exported namespace automatically when modules require it:

_.mixin(_.str.exports());

The docs are a bit vague but I think I put it in the shim init section? I tried the below but I can't even get a breakpoint to hit in the init:

require.config({
    paths: {
        jquery: 'libs/jquery/jquery.min',
        underscore: 'libs/underscore/lodash.min',
        underscorestring: 'libs/underscore/underscore.string.min'
    },

    shim: {
        underscore: {
            exports: '_'
        }
        underscorestring: {
            deps: ['underscore'],
            init: function (_) {
                //Mixin plugin to namespace
                _.mixin(_.str.exports());

                return _;
            }
        }
    }
});

When I try to do this and use underscorestring, I get this error:

Uncaught TypeError: Object function s(e){return new o(e)} has no method 'startsWith'

Docs:

  • http://requirejs.org/docs/api.html#config-shim
  • http://requirejs.org/docs/api.html#config-callback
like image 963
TruMan1 Avatar asked Nov 29 '12 13:11

TruMan1


People also ask

What is the use of RequireJS plugin?

RequireJS - Plugins. RequireJS contains a small set of plugins which allow loading various types of resources as dependencies. text. The text plug-in is used for loading text based resources asynchronously which is mainly used for inserting the HTML content in JavaScript files.

When to use a JS mixin?

Another use-case for the JS mixin is when the base Javascript file returns an object. In this case, a wrapper is necessary. The following example mixin extends the setHash method of step navigator object. Here, this._super () is the base method that can be called if needed. File: ExampleCorp/Sample/view/frontend/web/js/model/step-navigator-mixin.js

How do mixins work in RequireJS-config?

The mixins configuration in the requirejs-config.js associates a target component with a mixin using their paths.

What are the resources in RequireJS?

RequireJS contains a small set of plugins which allow loading various types of resources as dependencies. text. The text plug-in is used for loading text based resources asynchronously which is mainly used for inserting the HTML content in JavaScript files.


2 Answers

I don't know if it's the correct way, but I got it working by inverting things so that underscore depends on underscore.string. Also, this way you don't have to require underscore.string.

require.config({
  shim: {
    'backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    },
    'underscore': {
      deps: ['underscore.string'],
      exports: '_',
      init: function(UnderscoreString) {
        _.mixin(UnderscoreString);
      }
    }
  },
  paths: {
    'backbone'          : 'lib/backbone',
    'jquery'            : 'lib/jquery/jquery',
    'text'              : 'lib/require/text',
    'underscore'        : 'lib/underscore',
    'underscore.string' : 'lib/underscore.string'
  }
});

.

Update: 3/14/2014

Underscore.js v1.6.0 brought back AMD compatibility and init() has been removed from RequireJS, so some refactoring is in order. To continue getting Underscore preloaded with Underscore.string I made a mixer module to pull them together.

New Require.js config

requirejs.config({
  paths: {
    'backbone'            : '../lib/backbone/backbone',
    'backbone.base'       : '../lib/backbone/backbone.base',
    'backbone.extensions' : '../lib/backbone/backbone.extensions',
    'jquery'              : '../lib/jquery/jquery',
    'text'                : '../lib/require/text',
    'underscore'          : '../lib/underscore/underscore',
    'underscore.mixed'    : '../lib/underscore/underscore.mixed',
    'underscore.string'   : '../lib/underscore/underscore.string'
  },
  shim: {
    'backbone.base': {
      deps: ['underscore.mixed', 'jquery'],
      exports: 'Backbone'
    },
  }
});

underscore.mixed

define([
  'underscore',
  'underscore.string'
], function(_, _s) {
  _.mixin(_s.exports());
  return _;
});

The final step is to replace all instances of 'underscore' with 'underscore.mixed' in module definitions. I attempted moving Underscore into a file named underscore.base.js and making the regular underscore the mixer (like the Backbone setup) to avoid this step. Underscore, being a named module, disagreed with the plan.

like image 80
Garrett Johnson Avatar answered Oct 08 '22 09:10

Garrett Johnson


Do you require underscorestring somewhere? Because if it isn't required, it won't be loaded. I managed to get it working with almost exactly the same code you posted:

require.config({
    paths: {
        underscore: [
            '//raw.github.com/documentcloud/underscore/master/underscore-min'
        ,   'lib/underscore'
        ]
    ,   underscorestring: 'https://raw.github.com/epeli/underscore.string/master/dist/underscore.string.min'
    }
,   shim: {
        underscore: { exports: '_' },
        underscorestring: {
            deps: ['underscore'],
            init: function(_) { 
                _.mixin(_.str.exports());
                return _; // guess, this is not needed.
            }
        }
    }
,   exclude: ['underscore']
});

require(['underscore', 'underscorestring'], function(_) {
    console.log( _.chars("i'm a happy string.") );
});
like image 43
nirazul Avatar answered Oct 08 '22 07:10

nirazul