RequireJS не работает в многостраничном проекте с библиотеками, размещенными на CDN (jQuery)

Я использую RequireJS для многостраничного проекта с структурой папок Javascript, которая выглядит как это (как вы делаете эти причудливые деревья снова в Markdown?):

common.js
lib/
-- jquery-1.9.1.min.js
-- modernizr-2.6.2.min.js
-- underscore-amd.min.js
page/
-- index.js
-- start.js
-- checkout.js

В любом случае, common.js - это мой основной файл script, где я устанавливаю параметры конфигурации. Вот что это выглядит:

файл common.js

// Configure RequireJS
requirejs.config({
    baseUrl: "assets/js/lib",
    paths: {
        page: '../page',
        jquery: [
            '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
            //If the CDN location fails, load from this location
            'jquery-1.9.1.min'
        ],
        modernizr: [
            '//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min',
            //If the CDN location fails, load from this location
            'modernizr-2.6.2.min'
        ],
        underscore: [
            'underscore-amd.min'
        ]
    }
});

Все вызовы страниц работают так, как ожидалось (при загрузке места CDN), но я не могу опустить голову над частью минимизации. Оптимизатор r.js просто отказывается сотрудничать, бросая Error: paths fallback not supported in optimizer. Please provide a build config path override for underscore, хотя в Underscore нет указанного CDN.

файл build.js

{
    appDir: '../www',
    baseUrl: 'js/lib',
    dir: '../www-built',
    mainConfigFile: '../www/assets/js/common.js',
    modules: [
        //First set up the common build layer.
        {
            //module names are relative to baseUrl
            name: '../common',
            include: ['jquery',
                      'modernizr',
                      'underscore'
            ]
        },
        // Now the page scripts
        {
            //module names are relative to baseUrl/paths config
            name: '../page-index',
            include: ['page/index'],
            exclude: ['../common']
        },
    ],
    paths: {
        jquery: "empty",
        modernizr: "empty"
    },
    optimize: "uglify2",
    removeCombined: true
}

Пожалуйста, помогите мне разобраться, как создать этот проект для создания common.js script вместе с отдельными сценариями страницы.

(Примечание. Я основал структуру моего файла build.js на в этом примере

Обновлено!

Я обновил вопрос, включив правильный синтаксис для empty: (спасибо Travis!), и теперь сборка работает без ошибок. Однако мои JS файлы не объединены или не очищены. Файлы CSS находятся в точках импорта, поэтому что-то происходит. Заполните build.js файл ниже (простите меня, но она высокая):

{
    appDir: '../www',
    baseUrl: 'assets/js', // relative to appDir
    dir: '../www-built',
    mainConfigFile: '../www/assets/js/common.js',
    modules: [
        //First set up the common build layer.
        {
            //module names are relative to baseUrl
            name: 'common',
            //List common dependencies here. Only need to list
            //top level dependencies, "include" will find
            //nested dependencies.
            include: ['jquery',
                      'modernizr',
                      'underscore',
                      'bootstrap'
            ]
        },

        //Now set up a build layer for each page, but exclude
        //the common one. "exclude" will exclude nested
        //the nested, built dependencies from "common". Any
        //"exclude" that includes built modules should be
        //listed before the build layer that wants to exclude it.
        //"include" the appropriate "app/main*" module since by default
        //it will not get added to the build since it is loaded by a nested
        //require in the page*.js files.
        {
            //module names are relative to baseUrl/paths config
            name: 'pages/home',
            include: ['pages/home'],
            exclude: ['common']
        },
        {
            //module names are relative to baseUrl/paths config
            name: 'pages/start',
            include: ['pages/start'],
            exclude: ['common']
        },
        {
            //module names are relative to baseUrl/paths config
            name: 'pages/checkout',
            include: ['pages/checkout'],
            exclude: ['common']
        },
    ],
    paths: {
        jquery: "empty:",
        modernizr: "empty:"
//        underscore: "empty:"
    },
    optimize: "uglify2",
    optimizeCss: "standard",
    removeCombined: true,
    preserveLicenseComments: false
}

Окончательное обновление (Yaay! It working)

Благодаря Тревису ниже, все отлично работает! (файлы становятся миниатюрами и конкатенированы). Поскольку его решение размещено на Dropbox и может быть потеряно в будущем (кто знает амирит?), Я просто подытожу исправления, которые он сделал:

1. Не смешивайте вызовы define и require в одном файле.

У меня было несколько файлов, где я их смешивал так:

страница /start.js

 define(['jquery','underscore'],function($,_) {
      ...
 });

 require(['jquery','page/start'], function($, Y) { // BAD!
      ...
 });

и исправление должно было сделать это:

страница /start.js

 require(['jquery','app/start_helper'], function($, Y) {
      ...
 });

приложение /start _helper.js

 define(['jquery','underscore'],function($,_) {
      ...
 });

2. Это "empty:" не "empty"

Это сложный вопрос, хотя упоминания о них требуют документы RequireJS.

3. Поскольку

в каком списке есть только 2 балла?


Awesomeelicious - теперь он работает как шарм:)

Ответы

Ответ 1

Похоже, что requireJs думает, что вы пытаетесь предоставить резервную копию пути для подчеркивания, поскольку вы указываете его значение пути как массив. Попробуйте просто сделать это как строку вместо.

paths: {
    underscore: 'underscore-amd.min'
}

Также обратите внимание, что правильный символ для пустых путей - empty: (с ':') не empty.

Наконец, в качестве несвязанной стороны вы всегда можете посмотреть lodash, которая является IMHO более настраиваемой, кросс-браузерной, более быстрой заменой подчеркивания с идентичным API и он размещен на cdnjs и совместим с AMD

UPDATE

Следуя за разговором в комментариях, здесь моя обновленная версия вашего проекта: https://dl.dropboxusercontent.com/u/21823728/so_rjs.tar.gz

Как уже упоминалось в комментариях, ваша проблема, похоже, заключалась в том, что вы были define встроенными модулями в том же файле, в котором вы нуждались в этих модулях, и что я считаю, что r.js полагает, что у этих модулей не было основная точка входа. Соглашение состоит в том, чтобы отделить определения модулей от файлов, требующих этих модулей.

Обратите внимание на папку app в разделе assets/js, где теперь хранятся каждый модуль, который раньше был define d в ваших модулях страниц. Теперь модули страниц теперь require включены в эти модули. Когда я снова запустил r.js (используя uglify2 в качестве оптимизатора), все, казалось, работало так, как ожидалось.

Кроме того, я удалил некоторую избыточность из файла build.js(вам нужно указать baseUrl в mainConfigFile, если тот, который вы используете для вашей конфигурации сборки). Наконец, вы можете захотеть изучить конфигурацию shim, если вы хотите присоединить jQuery и Bootstrap глобально к каждой странице. В противном случае вам следует просто указать их как зависимости, когда они вам понадобятся.

Наконец, в качестве одного из последних советов вам может потребоваться сократить количество require в каждом файле. На большинстве этих страниц вы можете обернуть все в один вызов, а затем просто разделить другую логику на функции, чтобы сохранить некоторое пространство в очереди событий, а также некоторые циклы, чтобы избыточно вызвать функцию require.