How to use AMD code completion with webstorm and requirejs? - requirejs

I have something like this
define(function(require) {
var Router = require('./router');
var Backbone = require('backbone');
var Log = require('log');
...
Apparently Webstorm is meant to support AMD modules but I can't get it to work, instead a get a massive list of properties from every .js file in the project.
Has anyone had any luck getting Webstorm code completion / refactoring with requirejs modules?
Update, I was able to get it working if I following the following construct
define(['backbone', './router', './log'], function(Backbone, Router, Log) {
however, all paths have to be relative. This is impractical for a path that is configured in require.config, so Backbone does not have code completion.
requirejs.config({
baseUrl: 'js',
paths: {
'backbone' : '../bower_components/backbone/backbone-min',
...
Plus, the above syntax becomes ugly when there are many dependencies...
update 2
The above does not work if you change directory, for example, the Log below does not get code completion:
define(['backbone', './router', '../utils/log'], function(Backbone, Router, Log) {

As commented above, the support for AMD and CustomJS modules is on the roadmap for WebStorm 8. The Early Access Program started recently offers a preview for the AngularJS and Spy-js support only, but the AMD support is in progress and I hope that it'd appear in the next update.
In the meanwhile, you can try the Require.js plugin which provides a partial support for the requirejs modules. You'll get path completion for the module dependencies in the define call, including the requirejs plugins recognition:
The code completion offers so many "false positives" that you'd better learn the interface of your objects and use the "IntelliSense" just as a hint or a help to finish long identifiers; I doubt that the plugin helps the IDE here:
Other features like finding usages or refactoring (rename file and rename object) do not work across the boundary of the module closure. You're better off with the Replace in Path feature...
Notes to the plugin: The path to the config file in the plugin settings is relative to the public directory (the base URL). Also, I'd recommend checking out the binary package from the github project site, which may offer a newer version than the WebStorm plugin manager. (The 0.13 downloaded from there fixed crashing of the plugin with my project, while the WebStorm IDE still offered the 0.12.)
UPDATE: The issue WEB-825 appears to be partially fixed in WebStorm-134.1081 downloadable from EAP. The Find Usages feature recognizes formal parameters initialized from the requirejs dependencies and searches for the module references in the project instead of for the variable reference in the current closure:
Refactoring has improved. Renaming a file in the projtect does affect all module references, but it introduces a relative path to the requirejs base directory (URL). For example, renaming toolitems.js in the src/model directory to menuitems.js changes all references from "model/toolitems" to "../model/menuitems"; providing the requirejs base directory is in the src directory. Renaming a method works in the entire project. Renaming an object works only within the scope of the current closure. Should work globally? You may intentionally choose different object names for the same module export in every closure with Require.js... Still, it is a good habit to use the same names for consistency and an improvement here would be nice.
The Require.js plugin, which brings a partial AMD support to WebStorm 7 seems not to be needed in WebStorm 8 anymore.
UPDATE II: The Require.js plugin still helps the WebStorm 8 users. It recognizes baseUrl and paths from the Require.js configuretion. You can map module path prefixes to different directory roots and still have to "Go To Location" feature working:
// file configured for the Require.js config file path
require.config({
paths: {
core: '../core/src',
recman: '../recman/src',
app: '.'
}
});
// Example of a module from the app project
define([
'core/model/node', 'recman/model/hold, 'app/view/manager'
], function (NodeModel, HoldModel, ManagerView) {
...
});

Related

babel-core 'transform' function cannot find plugin

I have a global node module that uses babel-core transform function.
I have no .babelrc at the root of my module.
It takes a file and basically just use transform to 'compile' it.
const result = transformSync(content, {
filename: src,
});
There is a .babelrc file along with the said file and I'm indeed able to find it
{
"presets": ["#babel/preset-env"]
}
but it complains about not finding '#babel/preset-env' which is right, because the module is installed with mine and not the file/.babelrc being transpiled.
I've tried many options in https://babeljs.io/docs/en/options but still can't make it work.
How can I configure transform so it get plugins from my module while loading babel configuration from the folder of the transpiled file ?
By design, Babel's plugin loader searches for plugins relative to the config file that references them, or uses the cwd for plugins passed directly in the transformSync options. Control of that isn't exposed to utilities calling Babel.
Changing those sematics would mean that a Babel config file would vary in behavior based on the tool that was loading it, which would be very inconsistent for users, especiall considering that one of the main benefits of having the config file format is so that config can easy be shared across multiple tools calling Babel, for instance one for tests and one for bundling.
If you want users to be able to customize your tool, it sounds like what you may actually want is your own entirely separate config file for your tool, so you can define whatever semantics you want for that.

Gulp + RequireJS Remove Vendor Files

I'm having a problem using Gulp to compile a RequireJS project properly. What I need to do is have gulp create a single distribution file that only includes the file necessary to have the application run.
In our application we are following a modular approach breaking out major pieces of functionality into different repos. So while developing my piece I have RequireJS including angular and many other vendor libraries that are common to all of the projects in the application. However when I go to move my piece into the larger application I no longer need these files in the final output since those dependencies also exist in that application (and having those extra libraries also makes the final distribution file over 300K).
I've tried creating another main.js (called gulp-main.js) file that only includes the dependencies that I need but when I run the gulp process it fails. I don't get an error but it seems to be failing because I'm not including the required dependencies for the project to build successfully. Below is the config object that is being passed to the RequireJS optimize method.
var config = {
baseUrl: 'app/',
mainConfigFile: 'app/main.js',
out: 'dist/app/output.js',
name: 'main'
};
Any ideas on what I could do to either remove the unnecessary vendor files or even split them into a single vendor and a single non-vendor file would really be appreciated. I have already tried using the modules array option but that does not produce the results that I am after since it seems to create a single file for each item defined not a single compiled JS file with all scripts contained within.
Thanks in advance.
When you don't want some file in your final output. add " ! " in Your gulp task's src
example :
gulp.src(['./app/*.js', '!./node_modules/**']) // '!./vendor-libraries-dest to igonore'

Intellij IDEA resolve local require() path [ node.js ]

I'm trying to avoid relative require() calls in my express setup. I'd also like to avoid placing my code in the node_modules folder. In short, I'm trying to implement any of the methods described in this gist.
Any of those solutions will work fine for executing code with node or npm. However, I'm trying to find a solution that will also be supported by Intellij IDEA's code resolver, i.e. trying to make sure "go to declaration" and autocomplete hinting works.
I've tried the following
Setting NODE_PATH in the run configuration.
Using a global prefix, i.e. require( global.__base + "mylib").
Adding a symlinked folder to node_modules/.
Adding a symlink from a lib/ folder to node_modules/lib/ does work, but comes with two caveats:
Changes to the source files aren't picked up automatically, so I have to manually "synchronize" node_modules/lib, and
When "going to declaration", IntelliJ (of course) opens node_modules/lib/mylib instead of lib/mylib. This can lead to confusion as the actual file and the symlinked file can be open in separate windows.
Instead of a different way to require local paths (all these methods do work with node after all), I'd be happy with a way to hint to IDEA that it should search the lib/ folder for sources.
So, I realised that if you add a library through Project Structure > Libraries, it won't actually be enabled.
Instead, go to Preferences > Languages & Frameworks > Javascript > Libraries and add a new library. Set the framework type to node_modules, Visibility to Project and add your lib folder.
After adding it, make sure the Enabled checkbox is checked.
That's it, Intellij can now resolve your require('mylib') paths.
Use whatever method from the gist mentioned in the question to actually get node to resolve the paths.

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.

Using require.js to load non-AMD files and files with other than .js extension

Is there any clean way to load files with other than js extension and not AMD content?
I use the enforceDefine config to make sure my actual AMD code works while developing.
So far I've managed to put together a plugin that sets enforceDefine to false, so I can load 3rd party libraries like so: require(['noamd!handlebars']). That doesn't seem too much hacky to me but I'd like to know if there's a better way.
I'm currently testing the noext plugin and it does its job but also in a kind of a hacky way. I've noticed that it applies the noext parameter twice to the url (test.txt?noext=1&noext=1). I can live with that but optimally I'd like to git rid of all extra parameters. Can that be done?
To load files that aren't JS (such as .handlebars, .mustache) then the text plugin will suit your purposes.
To load normal js files you can use RequireJS as a script loader:
require(['full/path/to/file.js'], function(){
// Fired when file is loaded but if non AMD
// no value will be passed to this function
});
If you would like to treat the non-AMD file as a module, then you can use the shim config to implement it.
you can append a ?MEH=BLAH to the end to stop the .js appending
eg
requirejs.config({
paths: {
"dynamicstripconfig": "../php/domain/config.php?dynamic=1"
}
});
Additionally there a plugin for that as well, but doesn't support paths -> https://github.com/millermedeiros/requirejs-plugins
Added a issue with fix for path support -> https://github.com/millermedeiros/requirejs-plugins/issues/47
If your file isn't actually a dynamic js file then use the text plugin -> https://github.com/millermedeiros/requirejs-plugins

Resources