Grunt&针对多应用程序项目的requirejs优化器

时间:2013-12-14 13:19:07

标签: javascript optimization requirejs task gruntjs

我遇到问题让Grunt对具有以下结构的项目执行requirejs优化:

static/js
    |── apps
        |── app.js
        |── dash.js
        |── news.js
        ... (many more 'app' files)
    |── build
    |── collections
    |── libs
    |── models
    |── util
    |── views

每个static/js/apps/*.js都应编译为包含相关依赖项的static/js/build/*.js(例如views/view1libs/query等。

目前正由基本的bash脚本执行:

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

我正在尝试转向基于Grunt的优化,Grunt.js中包含以下内容:

requirejs: {
    compile: {
        options: {
            appDir: 'static/js/',
            baseUrl: './apps/',
            dir: 'static/js/build/',
            modules: [
                {
                    name: 'app',
                }
            ]
        }
    }
}

Running会生成以下错误:

>> Tracing dependencies for: app
>> Error: ENOENT, no such file or directory
>> 'static/js/build/apps/libs/jquery.js'
>> In module tree:
>>     app

我可以清楚地看到问题所在,但我未能弄清楚如何表明每个static/js/apps/*.js文件中的依赖项都在static/js/而不是static/js/build

除此之外,我假设包含modules的{​​{1}}块应该从name: 'app'的内容输出编译文件static/js/build/app.js

如果不为static/js/apps/app.js中的每个文件创建额外的module块,如何将每个文件编译到相关的static/js/apps文件中?

更新1

因此,我的Gruntfile中的以下内容将static/js/build/*.js成功编译为static/js/apps/app.js

static/js/build/app.js

下一步是将requirejs: { compile: { options: { baseUrl: 'static/js/', include: './apps/app.js', out: 'static/js/build/app.js', } } } 编译成static/js/apps/*.js,而不必单独定义每个...

更新2

将上述内容修改为:

static/js/build/*.js

创建任务:

requirejs: {
    compile: {
        options: {
            baseUrl: '../',
            include: './apps/<%= appFile %>',
            out: 'static/js/build/<%= appFile %>',
        }
    }
}

几乎让我找到解决方案。任务遍历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'); }); }); 中的每个文件,并将文件名传递到static/js/apps/。任务的输出会输出grunt.config.set('appFile', filename);等,但之后实际的Compiling app.js Compiling news.js...任务会在&amp;在requirejs:compile目录中的最后一个文件,而不是每个单独的文件。一个异步问题?

2 个答案:

答案 0 :(得分:11)

解决了,通过将多组选项传递给requirejs任务,感谢this article我需要的最终指针:

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,
    });
};

然后['requirejs']任务可以正常运行,并根据options: {}中指定的每个requirejsOptions块输出相应的已编译.js文件,例如:

grunt.registerTask('default', ['requirejs']);

答案 1 :(得分:0)

您需要在requirejs build config中将baseUrl从 apps 更改为 static / js 。由于当前baseUrl指向 apps 目录,因此require正在尝试搜索apps目录中的依赖项文件。如果您将baseUrl更改为 static / js ,它将找到这些依赖项文件。

   requirejs: {
     compile: {
       options: {
         appDir: 'static/js/',
         baseUrl: 'static/js',
         dir: 'static/js/build/',
         modules: [
          {
                name: 'app',
          }
         ]
       }
     }
   }