requirejs: parse a file and return its dependencies - requirejs

I have a situation where I need to load (via AJAX in a browser) a file that defines a requirejs module (without executing it) and get back a list of its dependencies.
Ie, given a file that starts with
requirejs(["foo/bar", "foo/baz"], function(bar, baz) {
I'd like the utility to return an array like
["foo/bar", "foo/baz"]
I've found some solutions that will do it using r.js (for example, the ones outlined here: https://groups.google.com/forum/#!msg/requirejs/4C0deWFqpZY/mkZFlw2r_k4J), but nothing to do it in a browser. I can just parse out the require statement myself, but that seems suboptimal. Has anyone come across any solutions for this?

Related

How should a RequireJS transpilation plugin return its result?

Transpilation plugins like es6!, es!, and cs! are more complicated than simple plugins like text! because they return javascript modules that have their own dependencies.
Specifically, the code I've seen loads the specified file through XHR, transforms it, and then returns the result via a call like
onload.fromText("define(['foo', 'bar', ...");
That works fine for small test cases but throws a "Mismatched anonymous define() module" exception when running in my actual app. It's a race condition that happens when RequireJS is simultaneously processing a bunch of normal JS requires at the same time as evaluating a bunch of plugin requires.
Is this just a RequireJS bug, or is the plugin doing it wrong? Or, is it just not supported? Despite multiple transpilation plugin examples on the web, the RequireJS doc on that error says that
If you use the loader plugins or anonymous modules (modules that call define() with no string ID) but do not use the RequireJS optimizer to combine files together, this error can occur.

Find function invocations across node files

Is there a way to find all the places across a project where a particular function is invoked? In particular, taking into account any times that the file is imported.
For example, if we're looking for where library.js's function foobar() is used, this example in another file would be included:
var library = require('./myfile.js')
library.foobar()
(The reason simply searching for foobar across all files won't work is if the function is a common name used in multiple modules.)
This would be the opposite of something like Webstorm's Jump to Definition feature.
One of the use-cases is to help refactor a legacy codebase where it's unclear where certain exported functions are being used, or if they're being used at all.
I saw similar questions like this one, but these seem to be for client-side javascript and don't take exports into account.
You can add
console.trace(); inside your function and you will know where does it called.
Sometime I use callsite module in the function I want to check for log the absolute link to file use this function.

Refactor multiple, similar requires (using Browserify)

I've got a very crude implementation working:
var screens = {
a: require('./../react_components/screens/a.jsx'),
b: require('./../react_components/screens/b.jsx'),
c: require('./../react_components/screens/c.jsx'),
d: require('./../react_components/screens/d.jsx'),
e: require('./../react_components/screens/e.jsx')
};
Which works fine, however, I'd like to make it a little more scalable, so that when I change a filename, or add a new file to the /screens folder, I don't really have to keep updating this list of require statements.
I'm using Browserify, so I do have a build step I can hook into if need be (this will be ran in the browser)
So for node/commonjs itself there are modules such as requireindex that will automate this kind of thing. However, the fact that these approaches determine the dependencies at runtime by looking at the filesystem defeats browserify's static analysis so I'm not aware of any of them that are browserify-compatible. Therefore, I'd suggest a code generation route where you use a module such as glob to discover the files you want to export, but then write out a full .js file with the exports all statically coded, and point browserify at that file, which you can regenerate every time during your build step.

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.

How to break the build into several files?

In case of a very lengthy built file, I would like to be able to break it into several parts. For instance, the vendors could be all minified into a vendor.built.js file and the rest into an app.built.js file.
How this can be done?
I have a proposed solution for this in my require-lazy project.
It accomplishes something a little different than what you ask though: It splits the application into lazy-loaded modules, as easy (from the developer's perspective) as writing (note the usage of the lazy! plugin):
define(["eager-module", "lazy!lazy-module"], function(eager, lazy) {...})
And then using it with through a promise:
lazy.get().then(function(real_module) {...});
The lazy-module will be loaded once, the first time .get() is called.
For the example above, the build process would produce 2 js files: On containing the main module, the eager-module and all their dependencies. And one containing the lazy-module and all its dependencies that were not included in the previous file/bundle.
The require-lazy project has a few examples that are very simple to setup, you only require Node.js.

Resources