Динамическое создание и минимизация JavaScript в серверном коде ASP.NET MVC

Я использую маршрут ASP.NET (для перехвата вызова.js) и контроллер для генерации JS, который я хочу использовать на своем клиенте. Причина, по которой я это делаю, состоит в том, чтобы не дублировать идентификаторы или константы на клиенте. Вот вывод моего JS:

app.serviceRootURL = 'http://localhost:65211/';  // set in my web.config
app.ajaxResponseStatuses = [
    { "status":"Success", "id":0 },              // set in my C# DTO
    { "status":"Failure", "id":1 },
];

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

Что еще более важно, мне интересно, как я могу связать и минимизировать это. Насколько я понимаю, даже если бы я мог минимизировать JS во время компиляции или во время выполнения, минификация изменит имена моих переменных. Так что в приведенном выше JS, app.ajaxResponseStatuses может быть изменен на a.bcи затем в реальных файлах JS, где я пытаюсь получить доступ к этой переменной, они могли искать x.yz,

  1. Можно ли минимизировать этот код и получить его на сервер?
  2. Смогу ли я использовать вышеуказанные свойства в других уменьшенных файлах?
  3. (бонусные баллы) Является ли это хорошим подходом для передачи серверных значений, которые будут использоваться на клиенте?

1 ответ

Решение

Часть 1

Если вы генерируете js во время выполнения, пакетирование невозможно (по крайней мере, неэффективно). Вы должны будете создать новый пакет для каждого запроса, который не очень быстрый. Кроме того, вы не сможете кэшировать обычный, постоянный пакет скриптов.

РЕДАКТИРОВАТЬ: Хотя объединение сгенерированных сервером js нецелесообразно, рендеринг значений в тег сценария на странице может обеспечить то же преимущество объединения, что и меньшее количество HTTP-вызовов. См. Редактирование в части 3 для получения дополнительной информации.

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

Часть 2

В большинстве минифайеров глобальные переменные (доступные на window объект) пропускаются во время искажения имени. При этом переменные, к которым обращаются в других файлах, которые не определены в этом файле, не переименовываются.

Например, если у вас есть следующий файл...

// outside of a closure, so globally accessible
var foo = 1;

function bar() {
  // within a closure, and defined with `var`, not globally accessible
  var bar;

  // reference to variable declared in another file
  baz = null;
}

это будет уменьшено следующим образом (с пробелами для удобства чтения)

var foo = 1;

function bar() {
  var b;

  baz = null;
}

Это одна из причин, по которой важно всегда объявлять переменные, используя var ключевое слово, в противном случае предполагается, что они являются ссылками на глобальные переменные и не будут минимизированы.

Кроме того, JSON (не литералы объектов Javascript!!!) никогда не будут искажаться минифайерами, потому что он состоит из строковых литералов для всех ключей и всех значений, которые не относятся к другому литеральному типу.

Часть 3

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

Default.aspx

<script> window.globals = <%= JsonConvert.SerializeObject(new AppGlobals(currentUser)) %>; </script>

Мы копируем это в код, но предпосылка та же.

РЕДАКТИРОВАТЬ:

Генерируемый сервером JS (на свой URI)

  • Pros

    • Кэшируется браузером (если свежие значения не нужны при каждом запросе)
  • Cons

    • Дополнительное путешествие туда и обратно
  • Используйте когда:

    • Сгенерированные файлы имеют большой размер, но редко меняются или одинаковы для нескольких пользователей. Эти сценарии могут обрабатываться так же, как и другие статические ресурсы. Чтобы привести пример, мы используем файл js, содержащий весь текст в нашем приложении для целей локализации. Мы можем обслуживать другой файл js в зависимости от языка, установленного в настройках пользователя, но эти значения меняются не более одного раза с каждым выпуском, поэтому мы можем установить агрессивные заголовки кэша и использовать хэш в URI вместе со строкой запроса для языковой стандарт для использования кэширования в браузере и загрузки каждого языкового файла только один раз для каждого клиента. Кроме того, если этот файл будет одинаковым для каждого пользователя, обращающегося к одному и тому же URI, вы можете кэшировать его на веб-сервере (IIS, Apache и т. Д.).
      Пример: /api/language.v1-0-0.js?locale=en

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

Сервер рендеринга JS (на странице в script тег)

  • Pros

    • Никаких дополнительных HTTP-вызовов
  • Cons

    • Может добавить дополнительный вес вашему HTML, который не может быть кэширован или уменьшен в зависимости от ваших обстоятельств
  • Используйте когда:

    • Ваши ценности часто меняются. Вес, добавленный на страницу, должен быть незначительным, если у вас нет огромного количества значений (в этом случае вы можете разделить их и добавить конечные точки API для этих значений и получать их только тогда, когда они нужны). Благодаря этому вы можете отключить дополнительный HTTP-вызов, поскольку js вставляется в тег сценария на странице, которую пользователь уже должен получить.

Но...

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

Другие вопросы по тегам