Автоверсионный CSS / JS в ASP.NET MVC? - PullRequest
14 голосов
/ 28 апреля 2011

Итак, я читал этот пост * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *. *.Приведенное решение вставляет номер сборки - что означает каждый раз, когда вы публикуете - он изменит КАЖДЫЙ ОДИНОЧНЫЙ файл, который не идеален , потому что если вы вносите изменения только в 1 * .css или * .js, то он будет менять каждыйи каждый файл.

1) Как это можно сделать только для «отдельных файлов» вместо использования всей сборки сайта с использованием даты модификации или чего-то еще в IIS7?

2) Также, если у меня есть некоторыесвоего рода «статический» актив, такой как - http://static.domain.com/js/123.js - как я могу использовать перезапись для отправки последнего файла для запроса, если кто-то встроил эту статическую ссылку на свой сайт?

т.е. http://static.domain.com/js/123.js это ссылка и при поступлении запроса на это - проверить и отправить последний файл?

Ответы [ 5 ]

17 голосов
/ 02 марта 2013

Я решил эту проблему, добавив автоматическую версию в свой проект MVC в файле AssemblyInfo.cs , например:

Change
[assembly: AssemblyVersion("1.0.0.0")]
to    
[assembly: AssemblyVersion("1.0.*")]

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

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

public static class UrlHelperExtensions
{
    public static string ContentVersioned(this UrlHelper self, string contentPath)
    {
        string versionedContentPath = contentPath + "?v=" + Assembly.GetAssembly(typeof(UrlHelperExtensions)).GetName().Version.ToString();
        return self.Content(versionedContentPath);
    }
}

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

<link href="@Url.ContentVersioned("style.css")" rel="stylesheet" type="text/css" />

При просмотре исходной страницы у вас теперь будет что-то похожее на

<link href="style.css?v=1.0.4809.30029" rel="stylesheet" type="text/css" />
6 голосов
/ 23 сентября 2011

1) Вместо этого используйте время изменения файла.Вот пример:

public static string GeneratePathWithTime(string cssFileName)
{
  var serverFilePath = server.MapPath("~/static/" + cssFileName);
  var version = File.GetLastWriteTime(serverFilePath).ToString("yyyyMMddhhmmss");
  return string.Format("/static/{0}/{1}", version, cssFileName);
}

Это сгенерирует путь, подобный «/static/201109231100/style.css» для «style.css» (при условии, что ваш style.css находится в каталоге static).Затем вы добавите правило перезаписи в IIS для перезаписи "/static/201109231100/style.css" в "/static/style.css".Номер версии будет изменен только тогда, когда файл CSS был изменен и применяется только к измененным файлам.

2) Вы можете обработать запрос к 123.js с помощью HttpModule и отправить его последнее содержимое, ноЯ не думаю, что вы можете гарантировать, что запрос получит последнюю версию.Это зависит от того, как браузер обрабатывает свой кеш.Вы можете установить более раннее время истечения (например, минуту назад) в своем заголовке ответа, чтобы браузеры всегда загружали файл заново, но сам браузер сам решает, загружать ли файл повторно или нет.,Вот почему нам нужно создавать разные пути для наших измененных файлов каждый раз, когда мы обновляли наши файлы в вашем вопросе 1), браузер всегда будет пытаться загрузить файл, если URL никогда ранее не посещался.

5 голосов
/ 08 декабря 2015

ОБНОВЛЕНИЕ: Предыдущая версия не работала на Azure, я упростил и исправил ниже.(Обратите внимание, что для работы в режиме разработки с IIS Express вам необходимо установить URL Rewrite 2.0 от Microsoft http://www.iis.net/downloads/microsoft/url-rewrite - он использует установщик WebPi, сначала закройте Visual Studio)

Если вы хотите изменить фактические имена файлов, а не добавлять строку запроса (которая игнорируется некоторыми прокси-серверами / браузерами для статических файлов) Вы можете выполнить следующие шаги: (Я знаю, что это старая запись, но янаткнулся на него при разработке решения:

Как это сделать: Автоматически увеличивать версию сборки при каждом построении проекта и использовать это число дляперенаправленный статический файл на определенные ресурсы, которые вы хотели бы обновлять (так что что-то .js включено как нечто. v1234.js с 1234, автоматически изменяющимся каждый раз при сборке проекта) - я также добавил некоторые дополнительные функции, чтобы гарантировать, что .min.js-файлы используются в производственной среде, а обычные.js-файлы используются при отладке (я использую WebGrease для автоматизациипроцесс минимизации) Одна из приятных особенностей этого решения заключается в том, что оно работает как в локальном / dev-режиме, так и в производственном режиме.(Я использую Visual Studio 2015 / Net 4.6, но я считаю, что это будет работать и в более ранних версиях.

Шаг 1: Включить автоматическое увеличение сборки при сборке В AssemblyInfoФайл .cs (находится в разделе «Свойства» вашего проекта, измените следующие строки:

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

на

[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

Шаг 2: Настройка URLпереписать в web.config для файлов со слагами встроенной версии (см. шаг 3)

В web.config (основной для проекта) добавьте следующие правила в раздел <system.webServer>, который я поместил непосредственно после</httpProtocol> end tag.

<rewrite>
  <rules>
    <rule name="static-autoversion">
      <match url="^(.*)([.]v[0-9]+)([.](js|css))$" />
      <action type="Rewrite" url="{R:1}{R:3}" />
    </rule>
    <rule name="static-autoversion-min">
      <match url="^(.*)([.]v[0-9]+)([.]min[.](js|css))$" />
      <action type="Rewrite" url="{R:1}{R:3}" />
    </rule>
  </rules>
</rewrite>

Шаг 3: Переменные приложения установки для чтения текущей версии сборки и создания слагов версий в файлах js и css.

в Global.asax.cs (находится в корне проекта) добавьте следующий код в защищенный void Application_Start () (после строк Register)

            // setup application variables to write versions in razor (including .min extension when not debugging)
            string addMin = ".min";
            if (System.Diagnostics.Debugger.IsAttached) { addMin = ""; }  // don't use minified files when executing locally
            Application["JSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.','0') + addMin + ".js";
            Application["CSSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.', '0') + addMin + ".css";

Шаг 4: Изменитьссылки SRC в представлениях Razor, используя переменные приложения, которые мыустановить в Global.asax.cs

@HttpContext.Current.Application["CSSVer"]
@HttpContext.Current.Application["JSVer"]

Например, в моем _Layout.cshtml, в моем разделе head, у меня есть следующий блок кода для таблиц стилей:

<!-- Load all stylesheets -->
<link rel='stylesheet' href='https://fontastic.s3.amazonaws.com/8NNKTYdfdJLQS3D4kHqhLT/icons.css' />
<link rel='stylesheet' href='/Content/css/main-small.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/medium.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/large.@HttpContext.Current.Application["CSSVer"]' />
@RenderSection("PageCSS", required: false)

Здесь следует отметить пару вещей: 1) в файле нет расширения .2) .min тоже нет.Оба они обрабатываются кодом в Global.asax.cs

Аналогично (также в _Layout.cs) в моем разделе JavaScript: у меня есть следующий код:

<script src="~/Scripts/all3bnd100.min.js" type="text/javascript"></script>
<script src="~/Scripts/ui.@HttpContext.Current.Application["JSVer"]" type="text/javascript"></script>
@RenderSection("scripts", required: false)

Первый файл - это пакет всех моих сторонних библиотек, которые я создал вручную с помощью WebGrease.Если я добавляю или изменяю какие-либо файлы в комплекте (что происходит редко), я вручную переименовываю файл в all3bnd101.min.js, all3bnd102.min.js и т. Д. Этот файл не соответствует обработчику перезаписи, поэтомубудет сохраняться в кэше в клиентском браузере, пока вы не перегруппируете / не измените имя вручную.

Второй файл - ui.js (который будет записан как ui.v12345123.js или ui.v12345123.min.jsв зависимости от того, работаете ли вы в режиме отладки или нет) Это будет обработано / переписано.(вы можете установить точку останова в Application_OnBeginRequest файла Global.asax.cs, чтобы посмотреть, как он работает)

Полное обсуждение этого вопроса: Упрощенное автоматическое управление версиями Javascript / CSS в ASP.NET MVC 5 для остановкипроблемы с кэшированием (работает в Azure и локально) с или без перезаписи URL (включая способ сделать это без перезаписи URL)

4 голосов
/ 14 августа 2012

Я написал Url Helper, который выполняет CacheBusting для меня.

public static string CacheBustedContent(this UrlHelper helper, string contentPath)
{
    var path = string.Empty;

    if (helper.RequestContext.HttpContext.Cache["static-resource-" + contentPath] == null)
    {
        var fullpath = helper.RequestContext.HttpContext.Server.MapPath(contentPath);
        var md5 = GetMD5HashFromFile(fullpath);
        path = helper.Content(contentPath) + "?v=" + md5;

        helper.RequestContext.HttpContext.Cache.Add("static-resource-" + contentPath, path, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(24, 0, 0), System.Web.Caching.CacheItemPriority.Default, null);
    }
    else
    {
        path = helper.RequestContext.HttpContext.Cache["static-resource-" + contentPath].ToString();
    }

    return path;
}

Вы можете заменить GetMD5HashFromFile () на CRC или любой другой вид вызова, который генерирует уникальную строку на основе содержимого или последнего-modified-date файла.

Недостатком является то, что он будет вызываться всякий раз, когда кеш становится недействительным.И если вы как-то измените файл в режиме реального времени, но не сбросите пул приложений, вам, вероятно, потребуется коснуться web.config, чтобы он перезагрузился правильно.

3 голосов
/ 24 сентября 2011

Возможно, вы захотите взглянуть на блог Дина Хьюма MVC и кэш приложений HTML5 .В этом посте он указывает на элегантный способ автоматической обработки версий для каждого запроса, используя библиотеку классов @ ShirtlessKirk :

@Url.Content("~/Content/Site.css").AppendHash(Request)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...