Не очищайте определенный файл при использовании Microsoft Web Optimization Framework

Я пытаюсь объединить множество .js файлов в один, используя Microsoft Web Optimization framework. Все работает, но внутри этих файлов у меня есть несколько, которые уже были минитизированы и угашены, и нет необходимости обрабатывать их снова.

Например, у меня есть файл recaptcha_ajax.js и он вызывает следующие ошибки при добавлении:

/* Minification failed. Returning unminified contents.
(715,29-36): run-time error JS1019: Can't have 'break' outside of loop: break t
(714,293-300): run-time error JS1019: Can't have 'break' outside of loop: break t
(678,210-217): run-time error JS1019: Can't have 'break' outside of loop: break t
(671,1367-1374): run-time error JS1019: Can't have 'break' outside of loop: break t
(665,280-287): run-time error JS1019: Can't have 'break' outside of loop: break t
 */

Я попытался взять recaptcha_ajax.js из пакета и ссылаться на него напрямую, но затем другие всплывающие окна - так что мне нужен этот файл внутри пакета в определенной позиции.

Мне просто нужно сказать - не уменьшайте и не угадывайте recaptcha_ajax.js - просто добавьте его в комплект.

Есть ли способ сделать это? Вот как я это вижу:

var b = new ScriptBundle("~/bundles/myjsbundle");

b.IncludeDirectory("~/ScriptsMine/", "*.js", true);

// some command like:
// b.DoNotMinifyOrUglify("~/ScriptsMine/recaptcha_ajax.js");

bundles.Add(b);

Ответ 1

Связки преобразуют каждый файл с помощью коллекции IItemTransform и конкатенации результата. Затем он преобразует результат, используя коллекцию IBundleTransform.

По умолчанию пакет script минимизирует содержимое всего пакета, используя JsMinify (который реализует IBundleTransform).

Итак, чтобы предотвратить минимизацию некоторого файла, вы должны создать свой собственный IBundleBuilder, который минимизирует файл пакета по файлу с помощью IItemTransform.

public class CustomScriptBundle : Bundle
{
    public CustomScriptBundle(string virtualPath)
        : this(virtualPath, null)
    {
    }

    public CustomScriptBundle(string virtualPath, string cdnPath)
        : base(virtualPath, cdnPath, null)
    {
        this.ConcatenationToken = ";" + Environment.NewLine;
        this.Builder = new CustomBundleBuilder();
    }
}


public class CustomBundleBuilder : IBundleBuilder
{
    internal static string ConvertToAppRelativePath(string appPath, string fullName)
    {
        return (string.IsNullOrEmpty(appPath) || !fullName.StartsWith(appPath, StringComparison.OrdinalIgnoreCase) ? fullName : fullName.Replace(appPath, "~/")).Replace('\\', '/');
    }

    public string BuildBundleContent(Bundle bundle, BundleContext context, IEnumerable<BundleFile> files)
    {
        if (files == null)
            return string.Empty;
        if (context == null)
            throw new ArgumentNullException("context");
        if (bundle == null)
            throw new ArgumentNullException("bundle");

        StringBuilder stringBuilder = new StringBuilder();
        foreach (BundleFile bundleFile in files)
        {
            bundleFile.Transforms.Add(new CustomJsMinify());
            stringBuilder.Append(bundleFile.ApplyTransforms());
            stringBuilder.Append(bundle.ConcatenationToken);
        }

        return stringBuilder.ToString();
    }
}

public class CustomJsMinify : IItemTransform
{
    public string Process(string includedVirtualPath, string input)
    {
        if (includedVirtualPath.EndsWith("min.js", StringComparison.OrdinalIgnoreCase))
        {
            return input;
        }

        Minifier minifier = new Minifier();
        var codeSettings = new CodeSettings();
        codeSettings.EvalTreatment = EvalTreatment.MakeImmediateSafe;
        codeSettings.PreserveImportantComments = false;

        string str = minifier.MinifyJavaScript(input, codeSettings);

        if (minifier.ErrorList.Count > 0)
            return "/* " + string.Concat(minifier.Errors) + " */";

        return str;
    }
}

Затем используйте CustomScriptBundle вместо ScriptBundle

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new CustomScriptBundle("~/bundles/Sample").Include(
                "~/Scripts/a.js",
                "~/Scripts/b.js",
                "~/Scripts/c.js"));
}

Если вы предоставите файл min.js, он будет использоваться вместо его извлечения.

Ответ 2

Рамка оптимизации учитывает имена файлов.

Попробуйте переименовать ваш *.js файл в recaptcha_ajax.min.js. Если я прав, то он должен пропустить процесс uglify/minify.

Справочные данные: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification (прокрутите немного вниз, чтобы найти эту цитату:)

Предыдущий код создает новый пакет JavaScript, названный ~/bundles/jquery, который включает все соответствующие (это отладка или, но не .vsdoc) в папке Scripts, которые соответствуют wild card string "~/Scripts/jquery- {version}.js". Для ASP.NET MVC 4, это означает, что при конфигурации отладки файл jquery-1.7.1.js будет быть добавлен в комплект. В конфигурации выпуска, Добавится jquery-1.7.1.min.js. Последовательность объединения несколько общих соглашений, таких как:

  • Выбор файла ".min" для выпуска, когда существуют "FileX.min.js" и "FileX.js".
  • Выбор версии ".min" для отладки.
  • Игнорирование файлов -vsdoc (таких как jquery-1.7.1-vsdoc.js), которые используются только IntelliSense.

Ответ 3

если вы добавляете файлы .js в ScriptManager, вы заметите, что сценарии загружаются в <form>, а не в <head>, поэтому вытаскивание из пакета будет загружать этот файл перед другими, что плохо если он зависит от других вещей в пакете

Вот пример библиотеки, которая должна быть добавлена ​​в комплект в определенном порядке.
Это добавлено в App_Start/BundleConfig.vb

'############################################################
' This is a ScriptManager Resource Definition 
' for use in a ScriptManager mapping
'############################################################
    Dim ResourceDef as ScriptResourceDefinition = New ScriptResourceDefinition()
    Dim ResourceName as  String = "ColorBox"

    'add the Resource Definition details
    ResourceDef.Path = "~/Scripts/colorbox/jquery.colorbox-min.js"
    ResourceDef.DebugPath = "~/Scripts/colorbox/jquery.colorbox.js"

    ScriptManager.ScriptResourceMapping.AddDefinition(ResourceName, ResourceDef)
'############################################################

Обратите внимание на использование ResourceDef.Path и ResourceDef.DebugPath. Какой файл будет включен, будет зависеть от того, что вы делаете публикацию Debug или Release

  • Отладка: нет "углификации"
  • Релиз: Total "uglification"

Это мой пакет ScriptManager, обратите внимание на размещение ColorBox, позиция означает много:

<asp:ScriptManager runat="server" >
    <Scripts>
        <asp:ScriptReference Name="jquery" />
        <asp:ScriptReference Name="jquery.ui.combined" />
        <asp:ScriptReference Name="ColorBox" />          
        <asp:ScriptReference Name="Infragistics" /> 
        <asp:ScriptReference Name="MsAjaxBundle" />
        <asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
        <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
        <asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
        <asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
        <asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
        <asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
        <asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
        <asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
        <asp:ScriptReference Name="WebFormsBundle" />
    </Scripts>
</asp:ScriptManager>