2015-09-28 9 views
1

Я пытаюсь использовать генератор Generator-Backbone для Yeoman с RequireJS.Генератор-генератор yeoman и RequireJS - concat все модули в один файл при сборке?

Мне не нужна ленивая загрузка RequireJS, я просто использую ее для управления зависимостями и организации. Это нормально, если он используется во время разработки, но когда я запускаю grunt:build, мне бы хотелось, чтобы он объединил все мои модули в один файл, чтобы минимизировать HTTP-запросы.

В настоящее время, когда я строю я получаю эту ошибку:

Running "requirejs:dist" (requirejs) task 
>> Error: Error: ENOENT, no such file or directory '/Users/Tom/Code/myApp/.tmp/scripts/templates.js' 
>> In module tree: 
>>  main 
>>  app 
>> 
>>  at Error (native) 

Если я смотрю каталог, то кажется, что файл templates.js создается в нужном месте с помощью задачи JST, однако он позже перезаписана другая задача до выполнения задачи requirejs.

Ниже моя структура каталогов, а также мой Gruntfile:

Каталог:

├── Gruntfile.js 
├── app 
│   ├── bower_components 
│   ├── index.html 
│   ├── scripts 
│   │   ├── main.js 
│   │   ├── modules 
│   │   │   └── admanager.js 
│   │   ├── templates 
│   │   │   ├── ads.ejs 
│   │   │   ├── app.ejs 
│   │   │   ├── content.ejs 
│   │   │   └── navigation.ejs 
│   │   └── views 
│   │    ├── ads.js 
│   │    ├── app.js 
│   │    ├── content.js 
│   │    └── navigation.js 
│   └── styles 
│    └── main.css 
├── bower.json 
├── dist 
├── node_modules 
├── package.json 
└── test 
    ├── index.html 
    └── spec 
     └── test.js 

Gruntfile:

'use strict'; 
var LIVERELOAD_PORT = 35729; 
var SERVER_PORT = 9000; 
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT}); 
var mountFolder = function (connect, dir) { 
    return connect.static(require('path').resolve(dir)); 
}; 


module.exports = function (grunt) { 

    require('time-grunt')(grunt); 
    require('load-grunt-tasks')(grunt); 

    // configurable paths 
    var yeomanConfig = { 
     app: 'app', 
     dist: 'dist' 
    }; 

    grunt.initConfig({ 
     yeoman: yeomanConfig, 
     watch: { 
      options: { 
       nospawn: true, 
       livereload: LIVERELOAD_PORT 
      }, 
      livereload: { 
       options: { 
        livereload: grunt.option('livereloadport') || LIVERELOAD_PORT 
       }, 
       files: [ 
        '<%= yeoman.app %>/*.html', 
        '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css', 
        '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js', 
        '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}', 
        '<%= yeoman.app %>/scripts/templates/*.{ejs,mustache,hbs}', 
        'test/spec/**/*.js' 
       ] 
      }, 
      jst: { 
       files: [ 
        '<%= yeoman.app %>/scripts/templates/*.ejs' 
       ], 
       tasks: ['jst'] 
      }, 
      test: { 
       files: ['<%= yeoman.app %>/scripts/{,*/}*.js', 'test/spec/**/*.js'], 
       tasks: ['test:true'] 
      } 
     }, 
     connect: { 
      options: { 
       port: grunt.option('port') || SERVER_PORT, 
       // change this to '0.0.0.0' to access the server from outside 
       hostname: 'localhost', 
       livereload: 35729 
      }, 
      livereload: { 
       options: { 
        base: [ 
         '.tmp', 
         '<%= yeoman.app %>' 
        ], 
        middleware: function (connect) { 
         return [ 
          lrSnippet, 
          mountFolder(connect, '.tmp'), 
          mountFolder(connect, yeomanConfig.app) 
         ]; 
        }, 
       } 
      }, 
      test: { 
       options: { 
        port: 9001, 
        middleware: function (connect) { 
         return [ 
          mountFolder(connect, 'test'), 
          lrSnippet, 
          mountFolder(connect, '.tmp'), 
          mountFolder(connect, yeomanConfig.app) 
         ]; 
        } 
       } 
      }, 
      dist: { 
       options: { 
        middleware: function (connect) { 
         return [ 
          mountFolder(connect, yeomanConfig.dist) 
         ]; 
        } 
       } 
      } 
     }, 
     open: { 
      server: { 
       path: 'http://localhost:9000' 
      }, 
      test: { 
       path: 'http://localhost:<%= connect.test.options.port %>' 
      } 
     }, 
     clean: { 
      dist: ['.tmp', '<%= yeoman.dist %>/*'], 
      server: '.tmp' 
     }, 
     jshint: { 
      options: { 
       jshintrc: '.jshintrc', 
       reporter: require('jshint-stylish') 
      }, 
      all: [ 
       'Gruntfile.js', 
       '<%= yeoman.app %>/scripts/{,*/}*.js', 
       '!<%= yeoman.app %>/scripts/vendor/*', 
       'test/spec/{,*/}*.js' 
      ] 
     }, 
     mocha: { 
      all: { 
       options: { 
        run: true, 
        urls: ['http://localhost:<%= connect.test.options.port %>/index.html'] 
       } 
      } 
     }, 
     requirejs: { 
      dist: { 
       // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js 
       options: { 
        /*added:*/ 
        wrap: true, 
        almond: true, 
        replaceRequireScript: [{ 
         files: ['<%= yeoman.dist %>/index.html'], 
         module: 'main' 
        }], 
        modules: [{name: 'main'}], 
        baseUrl: '<%= yeoman.app %>/scripts', 
        mainConfigFile: '<%= yeoman.app %>/scripts/main.js', 
        dir: '.tmp/scripts', 
        optimize: 'none', 
        useStrict: true, 
        paths: { 
         'templates': '../../<%= yeoman.app %>/scripts/templates', 
         'jquery': '../../<%= yeoman.app %>/bower_components/jquery/jquery', 
         'underscore': '../../<%= yeoman.app %>/bower_components/lodash/dist/lodash', 
         'backbone': '../../<%= yeoman.app %>/bower_components/backbone/backbone' 
        } 
        /*end added*/ 

        /* 
        baseUrl: '<%= yeoman.app %>/scripts', 
        optimize: 'none', 
        paths: { 
         'templates': '../../.tmp/scripts/templates', 
         'jquery': '../../<%= yeoman.app %>/bower_components/jquery/dist/jquery', 
         'underscore': '../../<%= yeoman.app %>/bower_components/lodash/dist/lodash', 
         'backbone': '../../<%= yeoman.app %>/bower_components/backbone/backbone' 
        }, 
        preserveLicenseComments: false, 
        useStrict: true, 
        wrap: true 
        */ 
       } 
      } 
     }, 
     /*added:*/ 
     uglify: { 
      dist: { 
       files: { 
        '<%= yeoman.dist %>/scripts/main.js': [ 
         '.tmp/scripts/main.js' 
        ] 
       } 
      } 
     },/*end added*/ 

     useminPrepare: { 
      html: '<%= yeoman.app %>/index.html', 
      options: { 
       dest: '<%= yeoman.dist %>' 
      } 
     }, 
     usemin: { 
      html: ['<%= yeoman.dist %>/{,*/}*.html'], 
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 
      options: { 
       dirs: ['<%= yeoman.dist %>'] 
      } 
     }, 
     imagemin: { 
      dist: { 
       files: [{ 
        expand: true, 
        cwd: '<%= yeoman.app %>/images', 
        src: '{,*/}*.{png,jpg,jpeg}', 
        dest: '<%= yeoman.dist %>/images' 
       }] 
      } 
     }, 
     cssmin: { 
      dist: { 
       files: { 
        '<%= yeoman.dist %>/styles/main.css': [ 
         '.tmp/styles/{,*/}*.css', 
         '<%= yeoman.app %>/styles/{,*/}*.css' 
        ] 
       } 
      } 
     }, 
     htmlmin: { 
      dist: { 
       options: { 
        /*removeCommentsFromCDATA: true, 
        // https://github.com/yeoman/grunt-usemin/issues/44 
        //collapseWhitespace: true, 
        collapseBooleanAttributes: true, 
        removeAttributeQuotes: true, 
        removeRedundantAttributes: true, 
        useShortDoctype: true, 
        removeEmptyAttributes: true, 
        removeOptionalTags: true*/ 
       }, 
       files: [{ 
        expand: true, 
        cwd: '<%= yeoman.app %>', 
        src: '*.html', 
        dest: '<%= yeoman.dist %>' 
       }] 
      } 
     }, 
     copy: { 
      dist: { 
       files: [{ 
        expand: true, 
        dot: true, 
        cwd: '<%= yeoman.app %>', 
        dest: '<%= yeoman.dist %>', 
        src: [ 
         '*.{ico,txt}', 
         'images/{,*/}*.{webp,gif}', 
         'styles/fonts/{,*/}*.*', 
        ] 
       }, { 
        src: 'node_modules/apache-server-configs/dist/.htaccess', 
        dest: '<%= yeoman.dist %>/.htaccess' 
       }] 
      } 
     }, 
     bower: { 
      all: { 
       rjsConfig: '<%= yeoman.app %>/scripts/main.js' 
      } 
     }, 
     jst: { 
      options: { 
       amd: true 
      }, 
      compile: { 
       files: { 
        // '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.ejs'] 
        '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.ejs'] 
       } 
      } 
     }, 
     rev: { 
      dist: { 
       files: { 
        src: [ 
         '<%= yeoman.dist %>/scripts/{,*/}*.js', 
         '<%= yeoman.dist %>/styles/{,*/}*.css', 
         '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}', 
         '/styles/fonts/{,*/}*.*', 
        ] 
       } 
      } 
     } 
    }); 

    grunt.registerTask('createDefaultTemplate', function() { 
     grunt.file.write('.tmp/scripts/templates.js', 'this.JST = this.JST || {};'); 
    }); 

    grunt.registerTask('server', function (target) { 
     grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); 
     grunt.task.run(['serve' + (target ? ':' + target : '')]); 
    }); 

    grunt.registerTask('serve', function (target) { 
     if (target === 'dist') { 
      return grunt.task.run(['build', 'open:server', 'connect:dist:keepalive']); 
     } 

     if (target === 'test') { 
      return grunt.task.run([ 
       'clean:server', 
       'createDefaultTemplate', 
       'jst', 
       'connect:test', 
       'open:test', 
       'watch' 
      ]); 
     } 

     grunt.task.run([ 
      'clean:server', 
      'createDefaultTemplate', 
      'jst', 
      'connect:livereload', 
      'open:server', 
      'watch' 
     ]); 
    }); 

    grunt.registerTask('test', function (isConnected) { 
     isConnected = Boolean(isConnected); 
     var testTasks = [ 
       'clean:server', 
       'createDefaultTemplate', 
       'jst', 
       'connect:test', 
       'mocha', 
      ]; 

     if(!isConnected) { 
      return grunt.task.run(testTasks); 
     } else { 
      // already connected so not going to connect again, remove the connect:test task 
      testTasks.splice(testTasks.indexOf('connect:test'), 1); 
      return grunt.task.run(testTasks); 
     } 
    }); 

    grunt.registerTask('build', [ 
     'clean:dist', 
     'createDefaultTemplate', 
     'jst', 
     'useminPrepare', 
     'imagemin', 
     'htmlmin', 
     'concat', 
     'cssmin', 
     'uglify:generated', 
     'copy', 
     'requirejs', 
     'uglify:dist', 
     'rev', 
     'usemin' 
    ]); 

    grunt.registerTask('default', [ 
     'jshint', 
     'test', 
     'build' 
    ]); 
}; 

Main.js:

/*global require*/ 
'use strict'; 

require.config({ 
    shim: { 
    }, 
    paths: { 
     // LIBS 
     jquery: '../bower_components/jquery/jquery', 
     backbone: '../bower_components/backbone/backbone', 
     underscore: '../bower_components/lodash/dist/lodash', 
     cookies: '../bower_components/js-cookie/src/js.cookie', 
     // CUSTOM MODULES 
     admanager: './modules/admanager', 
     // APP-SPECIFIC 
     app: '../scripts/views/app', 
     content: '../scripts/views/content', 
     ads: '../scripts/views/ads', 
     navigation: '../scripts/views/navigation' 
    } 
}); 

require([ 
    'backbone', 
    'app', 
], function (Backbone, App) { 
    Backbone.history.start(); 
    window.myApp = new App(); 
}); 

ответ

0

I потратил почти 2 э чтобы решить эту проблему и, наконец, понять ее. Ниже, как моя requireJs задача выглядит

options: { 
    wrap: true, 
    almond: true, 
    name: "../../<%= yeoman.app %>/bower_components/almond/almond", 
    include: ['main.js'], 
    out: "<%= yeoman.dist %>/scripts/app.js", 
    replaceRequireScript: [{ 
    files: ['<%= yeoman.dist %>/index.html'], 
    module: 'main' 
    }], 
    baseUrl: '<%= yeoman.app %>/scripts', 
    mainConfigFile: '<%= yeoman.app %>/scripts/main.js', 
    optimize: 'uglify2', 
    useStrict: true, 
    paths: { 
    'templates': '../../.tmp/scripts/templates', 
    'jquery': '../../<%= yeoman.app %>/bower_components/jquery/dist/jquery', 
    'underscore': '../../<%= yeoman.app %>/bower_components/lodash/dist/lodash', 
    'backbone': '../../<%= yeoman.app %>/bower_components/backbone/backbone' 
    } 
} 

Вы отсутствуют некоторые варианты, как name, include, out. Также не следует использовать dir.

Это как registeredTask 'сборки' выглядит как

grunt.registerTask('build', [ 
    'clean:dist', 
    'createDefaultTemplate', 
    'jst', 
    'sass:dist', 
    'useminPrepare', 
    'imagemin', 
    'htmlmin', 
    'concat', 
    'cssmin', 
    'uglify', 
    'copy', 
    'requirejs', 
    'rev', 
    'usemin' 
]); 

Эта конфигурация работала для меня. Надеюсь, это сработает и для вас.

+0

Спасибо за ваши усилия! Я сейчас не в своем окружении, поэтому я не могу проверить, но мне любопытно, как это будет выполняться во время разработки (скажем, с помощью регулярной «сервировки grunt»)? Будет ли он по-прежнему строить один файл или он будет использовать регулярную загрузку модуля requirejs? Я предполагаю, что более поздняя версия предпочтительнее во время dev, потому что 1) задача будет завершена/обслуживаться быстрее и 2) легче отлаживается, так как она не конкатенирована/не уменьшена. Интересует ваши мысли и не могу дождаться, чтобы попробовать! – Prefix

+0

@Prefix: Привет. Для сервисов grunt он будет использовать регулярную загрузку модуля js (легко отлаживается). Для сборки используется только миндаль, и все файлы js объединяются в один файл. – Dhiraj