Reason
In my case it was because I specified dependencies in requirejs's shim, for a library (perfect-scrollbar) that already supports AMD loading. The result is that the whole of its code in define is bypassed after grunt-contrib-requirejs did its job.
Basically, to concat requirejs files together, grunt-contrib-requirejs would
// change this:
define(['d3'],function(d3){...});
// into this:
define('d3', ['d3'],function(d3){...});
Whereas inside perfect-scrollbar, there's already
(function (factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['jquery'], factory); // <-------------------------- this part
    // after minification would become:
    // define('PerfectScrollbar', ['jquery'], factory);
  } else if (typeof exports === 'object') {
    factory(require('jquery')); // Node/CommonJS
  } else {
    factory(jQuery); // Browser globals
  }
}(function ($) {
  // perfect-scrollbar code here...
});
Which conflicted with what I specified in shim:
shim: {
    "PerfectScrollbar": ['jquery', 'jquery.mousewheel']
}
Therefore when requirejs got to the part where PerfectScrollbar was really defined, it hopped over it, assuming that it has already done the job.
Solution
Don't specify dependencies in shim for libraries that already have AMD support.
Question
But what if I need to specify dependencies? I need jquery.mousewheel on top of the jquery it already specified in its code.
Answer
Require that file with proper require, and get its own dependencies right:
define(['perfect-scrollbar', 'jquery.mousewheel'], function(){...});
Either when the library you need has AMD support,
// inside jquery.mousewheel:
require(['jquery'], factory);
Or it doesn't
shim: {
    "IDontSupportAMD": ['jquery']
}