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

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

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.

Google Closure Compiler to concatenate files using requirejs

I am using Google Closure compiler to concatenate and minify files. I am using require and my module depends on some JS files. Part of the JS files belong to an internal JS framework and several others depend on modules which our team has written. My aim is to concatenate all the dependencies in 1 file and then minimize it. Following is the code (the files prefixed with 'oj' are the framework files)
define(['ojs/ojcore',
'knockout',
'jquery',
'generalApp',
'modules/helpers',
'modules/facade/mrd',
'modules/facade/trf',
'modules/facade/crf',
'modules/models/sm',
'modules/models/mm',
'modules/list/dls',
'modules/utils/cm',
'ojs/ojchart',
'ojs/ojmasonrylayout',
'ojs/ojmenu',
'ojs/ojbutton',
'ojs/ojfilmstrip',
'ojs/ojarraytabledatasource',
'ojs/ojselectcombobox',
'ojs/ojdialog',
'ojs/ojcheckboxset',
'ojs/ojpagingcontrol'
], function (oj, ko, $, app, helpers, mrf, trf,crf, sm, mm, dls, cm) {
});
These files are in-turn dependent on other JS files and I only want the dependent JS files to get concatenated in the final JS file. Any idea how to do the concatenation using the Google Closure Compiler?
I tried using --process_common_js_modules --transform_amd_modules flags but the compiler threw errors since its unable to find the framework files which are located under ojs. There is a requirejs configuration file in which we are declaring path variables but I dont know how to specify the config file during the concatenation process.
Thanks in advance
Closure-compiler does not know how to order dependencies natively with AMD modules. Instead, use the requirejs compiler to concatenate the files in the correct order and then use closure-compiler for minification. This is done by setting the requirejs optimize flag to none.

How get grunt-closure-compiler to apply minimization to each file separately in a directory

Is there a way I can get grunt-closure-compiler to apply minimization to each file separately in a directory (overriding the original) instead of producing a single file as the output. If I can't override the original I am happy to place output files in a separate output directory.
https://github.com/gmarty/grunt-closure-compiler
Normally the procedue would be like this producing a single file:
grunt.initConfig({
'closure-compiler': {
frontend: {
closurePath: '/src/to/closure-compiler',
js: 'static/src/frontend.js',
jsOutputFile: 'static/js/frontend.min.js',
maxBuffer: 500,
options: {
compilation_level: 'ADVANCED_OPTIMIZATIONS',
language_in: 'ECMASCRIPT5_STRICT'
}
}
}
});
You can use the module option of the Closure Compiler to produce multiple output files. You would have to list each JavaScript file as its own module, so if you have many JavaScript files this could be pretty tedious.
The module option is not very well documented, but see the posts below to see how it works:
Using the Module Option in Closure Compiler to Create Multiple
Output Files
How do I split my javascript into modules using Google's Closure
Compiler?
As the other answer suggests, you need the modules option. However grunt-closure-compiler doesn't actually support this.
There's a fork of it which supports modules. It doesn't use the standard grunt file config so you can't use globbing patterns to get it to take all of the files in a folder. I've gotten around this by writing a grunt task to create the modules object and pass it into the config for the closure-compiler task.

Use Require.js with an external concatenation tool

Currently, I use YUI-compressor to concatenate and compress all my JavaScript files. However, for various reasons, I want to start using Require.js.
In development, the files are not concatenated, so I can just use the default require(filepath) and define(modulename) with Require.js. But how do I handle the fact that in production, YUI will compress all the files, thus invalidating all the filepaths in my requires?
Let's say I have one main.js which requires module1.js. Here's what I want to do:
Development
require('path-to-module1')... // main.js
define('module1', function()})... // module1.js
Production
require('module1')... // main.js. here though, module1 and main.js are combined.
define('module1')... // yeah, still same file.
It's best to use and AMD optimizer, for example r.js, to concatenate your files. You can then also use r.js to minify, or you could YUI-comressor to minify .
Read more about r.js optimizer here http://requirejs.org/docs/optimization.html.
And check out this repo for a good example project for how to use Require.js and how to optimize it https://github.com/volojs/create-template. You can run node tools/r.js -o tools/build.js after cloning that repo to see optimizer in action - it will combine all js files in www to a single file.
Finally, you should never name your modules, like
define('module1', [], function () {});
Always use anonymous modules like so:
define(["jquery"], function ($) {});
or
define(function (require) { var $ = require("jquery"); });
AMD optimizer will use the name your modules for you such that they can all live in one file, but you won't have to worry about that.
Hope this helps.

How to use AMD code completion with webstorm and 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) {
...
});

Resources