명시적인 ScriptBundle 포함 순서를 어떻게 지정할 수 있습니까?


91

나는 밖으로 시도하고 MVC4 System.Web.Optimization 1.0 ScriptBundle 기능을 .

다음 구성이 있습니다.

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        // shared scripts
        Bundle canvasScripts =
            new ScriptBundle(BundlePaths.CanvasScripts)
                .Include("~/Scripts/modernizr-*")
                .Include("~/Scripts/json2.js")
                .Include("~/Scripts/columnizer.js")
                .Include("~/Scripts/jquery.ui.message.min.js")
                .Include("~/Scripts/Shared/achievements.js")
                .Include("~/Scripts/Shared/canvas.js");
        bundles.Add(canvasScripts);
    }
}

및 다음보기 :

<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>

어디 BundlePaths.CanvasScripts입니다 "~/bundles/scripts/canvas". 다음을 렌더링합니다.

<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>

지금까지는 ~/Scripts/Shared/achievements.js번들 된 소스의 첫 번째 스크립트를 제외하고 는 훌륭 합니다. 이전에 포함 된 모든 스크립트에 따라 ScriptBundle. 번들에 include 문을 추가하는 순서를 준수하는지 어떻게 확인할 수 있습니까?

최신 정보

이것은 비교적 새로운 ASP.NET MVC 4 응용 프로그램 이었지만 최적화 프레임 워크 사전 릴리스 패키지를 참조하고있었습니다. 나는 그것을 제거하고 http://nuget.org/packages/Microsoft.AspNet.Web.Optimization 에서 RTM 패키지를 추가했습니다 . web.config에서 debug = true 인 RTM 버전을 사용 @Scripts.Render("~/bundles/scripts/canvas")하면 개별 스크립트 태그를 올바른 순서로 렌더링합니다.

web.config에서 debug = false를 사용하면 결합 된 스크립트가 먼저 achievements.js 스크립트를 가지지 만 나중에 호출되는 함수 정의 (객체 생성자)이므로 오류없이 실행됩니다. 아마도 미니 파이어가 의존성을 알아낼만큼 똑똑할까요?

또한 IBundleOrdererDarin Dimitrov가 두 디버그 옵션을 사용하여 RTM에서 제안한 구현을 시도 했으며 동일하게 작동했습니다.

따라서 축소 된 버전은 내가 예상 한 순서가 아니지만 작동합니다.

답변:


18

RTM 비트에서이 동작이 보이지 않습니다. Microsoft ASP.NET 웹 최적화 프레임 워크 1.0.0 비트를 사용하고 있습니까? http://nuget.org/packages/Microsoft.AspNet.Web.Optimization ?

새로운 MVC4 인터넷 응용 프로그램 웹 사이트를 기반으로 샘플과 유사한 재현을 사용했습니다.

BundleConfig.RegisterBundles에 추가했습니다.

        Bundle canvasScripts =
            new ScriptBundle("~/bundles/scripts/canvas")
                .Include("~/Scripts/modernizr-*")
                .Include("~/Scripts/Shared/achievements.js")
                .Include("~/Scripts/Shared/canvas.js");
        bundles.Add(canvasScripts); 

그런 다음 기본 색인 페이지에서 다음을 추가했습니다.

<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>

번들의 축소 된 자바 스크립트에서 achievements.js의 내용이 modernizr 이후임을 확인했습니다.


1.0 버전으로 업그레이드했습니다. 업데이트 된 질문을 참조하십시오. achievements.js의 내용은 축소 된 버전에 먼저 포함되지만 나중에 호출되는 함수이기 때문에 작동합니다.
jrummell

115

IBundleOrderer등록한 순서에 번들이 포함되도록 하는 사용자 지정 번들 주문자 ( )를 작성할 수 있습니다.

public class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
    {
        return files;
    }
}

그리고:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        var bundle = new Bundle("~/bundles/scripts/canvas");
        bundle.Orderer = new AsIsBundleOrderer();
        bundle
            .Include("~/Scripts/modernizr-*")
            .Include("~/Scripts/json2.js")
            .Include("~/Scripts/columnizer.js")
            .Include("~/Scripts/jquery.ui.message.min.js")
            .Include("~/Scripts/Shared/achievements.js")
            .Include("~/Scripts/Shared/canvas.js");
        bundles.Add(bundle);
    }
}

그리고 당신의 관점에서 :

@Scripts.Render("~/bundles/scripts/canvas")

10
이것은 작동해야하지만 기본 순서 지정자가 일반적으로 포함의 순서를 존중하기 때문에 불필요해야합니다 (jquery, reset.css / normalize.css 등 몇 가지 특수 파일 만 맨 위에 올림). achievements.js를 최고로 홍보해서는 안됩니다.
Hao Kung

1
@flipdoubt 파일을 여기에 재현하여 문제를 제기하십시오. aspnetoptimization.codeplex.com/workitem/list/advanced
Hao Kung

1
이것은 완벽하게 작동합니다, 감사합니다! 나는 동의하지만 이것은 필요하지 않습니다.
CBarr

2
이것은 나를 위해 작동합니다. stackoverflow.com/questions/17367736/… 에 따르면 부트 스트랩보다 jqueryui를 홍보하고있었습니다 .
Sethcran 2014 년

1
@Hao Kung include 디렉토리 의 파일을 주문할 수 있습니까?
shaijut

52

다린 감사합니다. 확장 방법을 추가했습니다.

internal class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
    {
        return files;
    }
}

internal static class BundleExtensions
{
    public static Bundle ForceOrdered(this Bundle sb)
    {
        sb.Orderer = new AsIsBundleOrderer();
        return sb;
    }
}

용법

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js",
                    "~/Scripts/jquery-migrate-{version}.js",

                    "~/Scripts/jquery.validate.js",
                    "~/Scripts/jquery.validate.messages_fr.js",
                    "~/Scripts/moon.jquery.validation-{version}.js",

                    "~/Scripts/jquery-ui-{version}.js"
                    ).ForceOrdered());

9
꽤 매끄러운! : D 지금 은 인터페이스 메서드 서명 을 변경 FileInfo해야 BundleFile했습니다. 그들은 그것을 바꿨습니다.
Leniel Maccaferri 2013

예 그들은 Owin 프레임 워크를 사용하는 프리 릴리즈 버전에서 변경했습니다
Softlion

약간 Off-Topic :이 BundleFile수업 에 대해 더 많은 정보가있는 사람이 있습니까? 포함 된 리소스를 번들로 묶기 위해 인스턴스화하려고하는데 VirtualFile생성자에 (구체적인 자식) 매개 변수가 필요합니다 .
superjos

나는 BundleFile의 인스턴스를 필요, 같은 질문을 가지고 있지만 방법을 모르는
루이

2
@superjos 나는 이것이 다소 오래되었다는 것을 알고 있지만 다른 사람이 문제가 있으면 대답 할 것입니다. System.Web.Optimization의 일부입니다.
Talon

47

MVC 5 (BundleFile vs FileInfo)의 변경 사항을 처리하기 위해 SoftLion에서 제공하는 답변을 업데이트했습니다.

internal class AsIsBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files)
    {
        return files;
    }
}

internal static class BundleExtensions
{
    public static Bundle ForceOrdered(this Bundle sb)
    {
        sb.Orderer = new AsIsBundleOrderer();
        return sb;
    }
}

용법:

    bundles.Add(new ScriptBundle("~/content/js/site")
        .Include("~/content/scripts/jquery-{version}.js")
        .Include("~/content/scripts/bootstrap-{version}.js")
        .Include("~/content/scripts/jquery.validate-{version}")
        .ForceOrdered());

나는 유창한 구문을 사용하는 것을 좋아하지만 단일 메서드 호출과 매개 변수로 전달 된 모든 스크립트에서도 작동합니다.


2
MVC 5에서 작동합니다. 감사합니다
Pascal Carmoni 2014-07-17

4
우수한. 이것은 MS 이럴으로 포함되어야한다
안젤로

Web Forms에서도 매력적으로 작동합니다 ... 기본적으로 모든 최신 버전에서 잘 작동합니다!
Sunny Sharma

매우 깨끗하고 간단한 솔루션입니다. 감사합니다.
bunjeeb

5

BundleCollection.FileSetOrderList의 도움으로 순서를 설정할 수 있어야합니다. 이 블로그 게시물을 살펴보세요 : http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . 인스턴스의 코드는 다음과 같습니다.

BundleFileSetOrdering bundleFileSetOrdering = new BundleFileSetOrdering("js");
bundleFileSetOrdering.Files.Add("~/Scripts/modernizr-*");
bundleFileSetOrdering.Files.Add("~/Scripts/json2.js");
bundleFileSetOrdering.Files.Add("~/Scripts/columnizer.js");
bundleFileSetOrdering.Files.Add("~/Scripts/jquery.ui.message.min.js");
bundleFileSetOrdering.Files.Add("~/Scripts/Shared/achievements.js");
bundleFileSetOrdering.Files.Add("~/Scripts/Shared/canvas.js");
bundles.FileSetOrderList.Add(bundleFileSetOrdering);

1

Cassette http://getcassette.net/ 사용을 고려해야 합니다. 각 파일에서 찾은 스크립트 참조를 기반으로 스크립트 종속성 자동 감지를 지원합니다.

MS 웹 최적화 솔루션을 선호하지만 스크립트 참조를 기반으로 스크립트를 배열하려는 아이디어가 마음에 들면 http://blogs.microsoft.co.il/oric/2013/12/27/building-single 에서 내 블로그 게시물을 읽어야합니다. -page-application-bundle-orderer /


1

@Darin Dimitrov의 답변은 저에게 완벽하게 작동하지만 내 프로젝트는 VB로 작성되었으므로 여기에 그의 답변이 VB로 변환되었습니다.

Public Class AsIsBundleOrderer
    Implements IBundleOrderer

    Public Function IBundleOrderer_OrderFiles(ByVal context As BundleContext, ByVal files As IEnumerable(Of FileInfo)) As IEnumerable(Of FileInfo) Implements IBundleOrderer.OrderFiles
        Return files
    End Function
End Class

그것을 사용하려면 :

Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle")
scriptBundleMain.Orderer = New AsIsBundleOrderer()
scriptBundleMain.Include(
    "~/Scripts/file1.js",
    "~/Scripts/file2.js"
)
bundles.Add(scriptBundleMain)

이 오류가 계속 발생합니다. Class 'AsIsBundleOrderer' must implement 'Function OrderFiles(context as ....)' for interface 'System.Web.Optimization.IBundleOrderer'아이디어가 있습니까?
Mark Pieszak-Trilon.io 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.