Как я могу использовать локальный файл во время оптимизации Require.js, но версию, размещенную в CDN, во время выполнения?

Моя страница включает в себя несколько компонентов, которые существуют как отдельные модули AMD. Каждый из этих компонентов преобразуется оптимизатором Require.js в отдельный файл. Поскольку некоторые из этих компонентов имеют общие зависимости (например, jQuery и d3), конфигурация оптимизатора paths использует URL-адреса CDN для этих зависимостей, а не объединяет их в оптимизированный файл.

Вот где это становится сложно. Я написал плагин загрузчика модулей для Ractive.js. с именем rvc.js, что позволяет мне включать компоненты Ractive, определенные в файлах HTML. (Да, я прошу помощи в том, как использовать мою собственную библиотеку.)

Это прекрасно работает — такой код оптимизируется, как и следовало ожидать:

define( function ( require ) {
  var ChartView = require( 'rvc!views/Chart' );
  var view = new ChartView({ el: 'chart' });
});

Поскольку Ractive используется несколькими компонентами, его следует обслуживать из CDN, такой как jQuery и d3. Но он используется rvc.js в процессе оптимизации, а это означает, что запись Ractive для конфигурации paths оптимизатора не может указывать на CDN — она должна указывать на локальный файл.

Есть ли способ указать Require.js «использовать локальный файл во время оптимизации, но загружать из CDN во время выполнения»?


person Rich Harris    schedule 25.02.2014    source источник
comment
установить переменную типа fileToUse= amILocal() ? lib.js : lib.min.js; и передайте fileToUse для требования вместо жестко закодированного литерала.   -  person dandavis    schedule 26.02.2014
comment
Проблема в том, что какое бы значение fileToUse ни было присвоено оптимизатору, это одновременно а) файл, используемый во время оптимизации, и б) файл, который оптимизатор включает (или пытается) в сборку. Таким образом, если fileToUse является локальным, локальный файл используется rvc.js во время оптимизации, но он также объединяется; если он удален, оптимизация не удалась.   -  person Rich Harris    schedule 26.02.2014


Ответы (1)


Итак, вот решение, на котором я в конце концов остановился. Это кажется несколько неуклюжим, но это работает:

  1. Заглушите загрузчики и библиотеку, которые вы не хотите связывать
  2. Добавьте функцию onBuildWrite, которая переписывает модули в зависимости от библиотеки, чтобы они думали, что им требуется что-то совершенно другое — в данном случае Ractive_RUNTIME
  3. Добавьте запись в объект paths конфигурации AMD во время выполнения, чтобы Ractive_RUNTIME указывал на CDN.

Моя конфигурация оптимизатора теперь выглядит так:

{
  baseUrl: 'path/to/js/',
  out: 'build/js/app.js',
  name: 'app',
  optimize: 'none',

  paths: {
    'amd-loader': 'loaders/amd-loader',
    'rvc': 'loaders/rvc',
    'Ractive': 'lib/Ractive'
  },

  stubModules: [ 'amd-loader', 'rvc', 'Ractive' ],

  onBuildWrite: function ( name, path, contents ) {
    if ( contents === "define('Ractive',{});" ) {
      // this is the stub module, we can kill it
      return '';
    }

    // otherwise all references to `Ractive` need replacing
    return contents.replace( /['"]Ractive['"]/g, '"Ractive_RUNTIME"' );
  }
}

Между тем, скрипт, который загружает файл app.js, созданный оптимизатором, имеет запись конфигурации, указывающую на CDN:

require.config({
  context: uniqueContext,
  baseUrl: baseUrl,

  paths: {
    'amd-loader': 'loaders/amd-loader',
    'rvc': 'loaders/rvc',
    'Ractive': 'lib/Ractive',
    'Ractive_RUNTIME': 'http://cdn.ractivejs.org/releases/0.3.9/Ractive.min'
  }
});
person Rich Harris    schedule 03.03.2014