I'm having issues getting Grunt to perform requirejs optimization on a project with the following structure:
static/js
|── apps
|── app.js
|── dash.js
|── news.js
... (many more 'app' files)
|── build
|── collections
|── libs
|── models
|── util
|── views
Each of static/js/apps/*.js
should be compiled to static/js/build/*.js
containing the relevant dependencies (eg. views/view1
, libs/query
etc).
This is currently being performed by a basic bash script:
JS_ROOT="static/js"
for f in ${JS_ROOT}/apps/*
do
FILE=$(basename -s .js ${f})
pushd .
cd ${JS_ROOT} && r.js -o baseUrl=. name=libs/require-min.js include=apps/${FILE} out=build/${FILE}.js
popd
done
I'm attempting to move to a Grunt-based optimization, with the following in Grunt.js
:
requirejs: {
compile: {
options: {
appDir: 'static/js/',
baseUrl: './apps/',
dir: 'static/js/build/',
modules: [
{
name: 'app',
}
]
}
}
}
Running generates the following error:
>> Tracing dependencies for: app
>> Error: ENOENT, no such file or directory
>> 'static/js/build/apps/libs/jquery.js'
>> In module tree:
>> app
I can clearly see what the problem is, but am failing to figure out how to indicate that the dependencies in each static/js/apps/*.js
file are in static/js/
not static/js/build
In addition to this, I'm assuming that the modules
block containing name: 'app'
should be outputting the compiled file static/js/build/app.js
from the contents of static/js/apps/app.js
.
Without creating an additional module
block for each file in static/js/apps
, how can I compile each of the files into their relevant static/js/build/*.js
file?
Update 1
So the following in my Gruntfile compiles static/js/apps/app.js
successfully into static/js/build/app.js
:
requirejs: {
compile: {
options: {
baseUrl: 'static/js/',
include: './apps/app.js',
out: 'static/js/build/app.js',
}
}
}
The next step being to compile static/js/apps/*.js
into static/js/build/*.js
without having to define each individually...
Update 2
Modifying the above to:
requirejs: {
compile: {
options: {
baseUrl: '../',
include: './apps/<%= appFile %>',
out: 'static/js/build/<%= appFile %>',
}
}
}
And creating the task:
grunt.registerTask('buildrjs', function() {
var dir='static/js/apps/';
grunt.file.setBase(dir);
var files = grunt.file.expand(['*.js']);
files.forEach(function(filename) {
grunt.log.write('Compiling '+filename+'\n');
grunt.config.set('appFile', filename);
grunt.task.run('requirejs:compile');
});
});
Almost gets me to the solution. The tasks runs through each file in static/js/apps/
and passes the filename into grunt.config.set('appFile', filename);
. The output of the task outputs Compiling app.js Compiling news.js...
etc, however afterwards the actual requirejs:compile
tasks runs over & over on the last file in the static/js/apps/
directory, rather than each individual file. An async issue?
Solved, by passing multiple sets of options to the requirejs task, thanks to this article for the final pointers I needed:
module.exports = function(grunt) {
var files = grunt.file.expand('static/js/apps/*.js');
var requirejsOptions = {};
files.forEach(function(file) {
var filename = file.split('/').pop();
requirejsOptions[filename] = {
options: {
baseUrl: 'static/js/',
include: './apps/'+filename,
out: 'static/js/build/'+filename
}
};
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
requirejs: requirejsOptions,
});
};
Then the ['requirejs']
task can be run as normal and will output the appropriate compiled .js file as per each of the options: {}
blocks that were specified in requirejsOptions
, eg:
grunt.registerTask('default', ['requirejs']);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With