В последнее время мы сталкивались с проблемами производительности NS-скриптов, и дело было не в нежелательных загрузках поиска/записи. По мере того, как наш пакет начал увеличиваться со временем, он начал вызывать проблемы с производительностью, поскольку мы постоянно добавляли новые функции. Именно тогда мы решили использовать прогрессивную загрузку NetSuite в наших сценариях на стороне сервера (таких как RESTlet, Suitelet, User-Events и т. д.), и это дало некоторые преимущества в производительности.

Итак, вот почему вам тоже нужно использовать прогрессивную загрузку в ваших скриптах и ​​модулях.

Предположим, у вас есть сценарий пользовательского события, в котором реализованы все/множественные функции входа, и вы запросили некоторые стандартные модули NetSuite вместе с некоторыми пользовательскими модулями с объектом определения, как показано ниже.

define([
  'N/record', 'N/search',
  './custom_customer_module', './custom_sales_order_module',
  './custom_module'
], function (record, search, CustomerModule, SalesOrderModule,
  SomeOtherModule
) {
  /**
   *
   * @param {Object} context
   * @prop  {String} context.type
   * @prop  {Object} context.newRecord
   * @prop  {Object} context.UserEventType
   */
  function beforeLoad(context) {
    var type = context.type;
    if (type !== context.UserEventType.CREATE) {
      return;
    }
    var seachResult = search.create({});
    // update some fields/data in newRecord
    
  }
  
  /**
   *
   * @param {Object} context
   * @prop  {Object} context.newRecord
   */
  function beforeSubmit(context) {
    var newRecord = context.newRecord;
    var recordType = newRecord.type;
    if (recordType === 'salesorder') {
       return SalesOrderModule.doSomething({ 
         salesOrder: newRecord 
       });
     } else if (recordType === 'customer') {
       return CustomerModule.doSomething(context);
     } else if (recodType === 'purchaseorder') {
       var someSalesOrder = record.load({ 
         type: 'salesorder', 
         id: SOME_SALES_ORDER,
         isDynamic: true
       });
       return SalesOrderModule.doSomething({ 
         salesOrder: someSalesOrder 
       });
     }
   }

   /**
    *
    * @param {Object} context
    * @prop  {Object} context.newRecord
    */
   function afterSubmit(context) {
     var newRecord = context.newRecord;
     return SomeOtherModule.processSomething(context);
   }
  return {
    beforeLoad: beforeLoad,
    beforeSubmit: beforeSubmit,
    afterSubmit: afterSubmit
  };
});

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

Оказывается, вы можете требовать эти модули, когда они вам действительно нужны. Это уменьшит время загрузки вашего скрипта, а некоторые скрипты, которые не используются, не будут загружены, если они вам не нужны ;).

Чтобы запрашивать/загружать сценарии во время загрузки, вам нужно использовать функцию require, предоставляемую NetSuite.

Теперь вы можете либо напрямую использовать его в своем скрипте, как показано ниже.

define([], function () { 
  function doSomethingInteresting() {
    require([SOME_MODULE], function (someModule) {
      // do something
    })
  }
}

или загрузите требуемый модуль, указав его в аргументах определения следующим образом

define(['require'], function (require) {}); 

Но между ними есть большая разница. Согласно NetSuite, используйте первый пример

Для импорта модулей по абсолютному пути.

т. е. путь к вашему модулю должен начинаться с Suite Scripts или Suite Bundle, например

Сценарии Suite/some_dir/custom_module

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

./some_dir/custom_module

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

Таким образом, в этом случае вы можете использовать второй подход и сначала загрузить требуемый модуль в define-object, это предоставит вам контекст сценария входа, а затем вы сможете постепенно загружать свои пользовательские модули по мере необходимости.

Вы также можете использовать прогрессивную загрузку для загрузки стандартных модулей NetSuite.

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

Вот пример сценария, который вы можете использовать для постепенной загрузки модулей в свои сценарии.

define([‘require’], function (require) {
  /**
   * @desc  `cb` is required for client-scripts, on server side require works synchronously.
   *
   * @param {String} path  module path like N/record or ./some_custom_module
   * @param {Callback} cb callback method used in client scripts
   */
  function getModule(path, cb) {
    var mod;
    
    require([path], function (m) { 
      mod = m;
      
      return cb 
        ? cb(mod) 
        : mod;
    });
    return mod;
  }
  return {
    getModule: getModule
  };
});

Для дальнейшего чтения проверьте документ NetSuite.