… 또는 내가 어떻게 걱정을 멈추고 마이크로 소프트의 완전히 문서화되지 않은 API에 대해 코드를 작성하는 법을 배웠습니다 . 공식 System.Web.Optimization
릴리스에 대한 실제 문서가 있습니까? ‘Cuz 나는 확실히 찾을 수없고, XML 문서도없고, 모든 블로그 게시물은 상당히 다른 RC API를 참조합니다. 아니 후 ..
자바 스크립트 종속성을 자동으로 해결하는 코드를 작성 중이며 해당 종속성에서 즉시 번들을 생성하고 있습니다. 스크립트를 편집하거나 응용 프로그램을 다시 시작하지 않고 번들에 영향을주는 변경 사항을 적용하는 경우를 제외하고 모든 것이 잘 작동합니다. 변경 사항이 반영되지 않습니다. 그래서 개발에 사용할 종속성 캐싱을 비활성화하는 옵션을 추가했습니다.
그러나 번들 컬렉션이 변경된 경우에도 분명히 BundleTables
URL을 캐시합니다 . 예를 들어 번들을 다시 만들고 싶을 때 내 코드에서 다음과 같이합니다.
// remove an existing bundle
BundleTable.Bundles.Remove(BundleTable.Bundles.GetBundleFor(bundleAlias));
// recreate it.
var bundle = new ScriptBundle(bundleAlias);
// dependencies is a collection of objects representing scripts,
// this creates a new bundle from that list.
foreach (var item in dependencies)
{
bundle.Include(item.Path);
}
// add the new bundle to the collection
BundleTable.Bundles.Add(bundle);
// bundleAlias is the same alias used previously to create the bundle,
// like "~/mybundle1"
var bundleUrl = BundleTable.Bundles.ResolveBundleUrl(bundleAlias);
// returns something like "/mybundle1?v=hzBkDmqVAC8R_Nme4OYZ5qoq5fLBIhAGguKa28lYLfQ1"
별칭이 같은 번들 을 제거하고 다시 만들 때마다 아무 일도 일어나지 않습니다. bundleUrl
반환 된 항목 ResolveBundleUrl
은 번들을 제거하고 다시 생성하기 전과 동일합니다. “동일”이란 번들의 새 콘텐츠를 반영하기 위해 콘텐츠 해시가 변경되지 않음을 의미합니다.
편집 … 사실, 그것은 그것보다 훨씬 더 나쁩니다. 번들 자체가 어떻게 든 외부의 캐시 Bundles
모음입니다. 브라우저가 스크립트를 캐싱하지 못하도록 내 임의의 해시를 생성하면 ASP.NET은 이전 스크립트를 반환 합니다 . 따라서 분명히 번들을 제거하는 BundleTable.Bundles
것은 실제로 아무것도하지 않습니다.
이 문제를 해결하기 위해 별칭을 간단히 변경할 수 있으며 개발에는 문제가 없지만 페이지가로드 될 때마다 별칭을 폐기해야하거나 크기가 커지는 BundleCollection이 있어야하기 때문에 그 아이디어가 마음에 들지 않습니다. 모든 페이지로드. 프로덕션 환경에이 기능을 그대로두면 재앙이 될 것입니다.
따라서 스크립트가 제공 될 때 실제 BundleTables.Bundles
객체와 독립적으로 캐시되는 것 같습니다 . 따라서 URL을 재사용하는 경우 재사용하기 전에 참조한 번들을 제거 했더라도 캐시에있는 모든 항목으로 응답하고 Bundles
객체를 변경해도 캐시가 플러시되지 않으므로 새 항목 만 (또는 오히려 다른 이름의 새 항목)이 사용됩니다.
동작이 이상해 보입니다. 컬렉션에서 무언가를 제거하면 캐시에서 제거해야합니다. 하지만 그렇지 않습니다. 이 캐시를 플러시하고 BundleCollection
해당 번들이 처음 액세스 될 때 캐시 된 내용 대신의 현재 내용을 사용하도록하는 방법이 있어야합니다 .
내가 어떻게 할 수 있을지 아십니까?
ResetAll
목적을 알 수없는 이 방법이 있지만 어차피 부수기 때문에 그렇지 않습니다.
답변
문서화에 대한 귀하의 고통을 들었습니다. 안타깝게도이 기능은 여전히 매우 빠르게 변경되고 있으며 문서 생성에는 약간의 지연이 있으며 거의 즉시 구식이 될 수 있습니다. Rick의 블로그 게시물 이 최신 상태이며, 그 동안 현재 정보를 전파하기 위해 여기에서 질문에 답하려고 노력했습니다. 우리는 현재 항상 최신 문서가있는 공식 codeplex 사이트를 설정하는 중입니다.
이제 캐시에서 번들을 플러시하는 방법에 대한 특정 문제와 관련하여.
-
요청 된 번들 URL에서 생성 된 키를 사용하여 번들 된 응답을 ASP.NET 캐시 내부에 저장합니다. 즉,
Context.Cache["System.Web.Optimization.Bundle:~/bundles/jquery"]
이 번들을 생성하는 데 사용 된 모든 파일 및 디렉터리에 대한 캐시 종속성도 설정합니다. 따라서 기본 파일이나 디렉토리가 변경되면 캐시 항목이 플러시됩니다. -
요청별로 BundleTable / BundleCollection의 라이브 업데이트를 실제로 지원하지 않습니다. 완전히 지원되는 시나리오는 앱 시작 중에 번들이 구성된다는 것입니다 (웹 팜 시나리오에서 모든 것이 제대로 작동하므로 일부 번들 요청이 잘못된 서버로 전송되면 404가됩니다). 코드 예제를 보면 특정 요청에 대해 번들 컬렉션을 동적으로 수정하려는 것 같습니다. 모든 종류의 번들 관리 / 재구성에는 모든 것이 올바르게 설정되었는지 확인하기 위해 appdomain 재설정이 수반되어야합니다.
따라서 앱 도메인을 재활용하지 않고 번들 정의를 수정하지 마십시오. 번들 내의 실제 파일을 자유롭게 수정할 수 있으며, 자동으로 감지되어 번들 URL에 대한 새 해시 코드를 생성해야합니다.
답변
비슷한 문제가 있습니다.
내 수업에서 BundleConfig
나는 BundleTable.EnableOptimizations = true
.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(...);
}
}
모든 것이 잘 작동했습니다.
어느 시점에서 디버깅을 수행하고 속성을 false로 설정했습니다.
나는 jquery (첫 번째) 번들이 해결되지 않고로드되지 않는 것처럼 보였기 때문에 무슨 일이 일어나고 있는지 이해하는 데 어려움을 겪었습니다 ( /bundles/jquery?v=
).
욕을 좀하고 나서 (?!) 정리해 낸 것 같아요. 추가하려고 bundles.Clear()
하고 bundles.ResetAll()
등록과 사물의 시작 부분에 다시 작업을 시작해야합니다.
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Clear();
bundles.ResetAll();
BundleTable.EnableOptimizations = false;
bundles.Add(...);
}
}
EnableOptimizations
속성을 변경할 때만이 두 가지 방법을 실행해야한다는 것을 깨달았습니다 .
최신 정보:
파고 깊은 나는 것을 발견했습니다 BundleTable.Bundles.ResolveBundleUrl
와 @Scripts.Url
번들 경로를 해결하기 위해 문제를 갖고있는 것 같다.
간단하게하기 위해 몇 가지 이미지를 추가했습니다.
최적화를 해제하고 몇 가지 스크립트를 번들로 제공했습니다.
동일한 번들이 본체에 포함되어 있습니다.
@Scripts.Url
@Scripts.Render
적절한 경로를 생성하는 동안 번들의 “최적화 된”경로를 제공합니다 .
같은 일이 BundleTable.Bundles.ResolveBundleUrl
.
Visual Studio 2010 + MVC 4 + Framework .Net 4.0을 사용하고 있습니다.
답변
웹 팜 시나리오로 인해이 작업을 수행하지 말라는 Hao Kung의 권장 사항을 염두에두고이를 수행하고 싶은 시나리오가 많이 있다고 생각합니다. 해결책은 다음과 같습니다.
BundleTable.Bundles.ResetAll(); //or something more specific if neccesary
var bundle = new Bundle("~/bundles/your-bundle-virtual-path");
//add your includes here or load them in from a config file
//this is where the magic happens
var context = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, bundle.Path);
bundle.UpdateCache(context, bundle.GenerateBundleResponse(context));
BundleTable.Bundles.Add(bundle);
언제든지 위 코드를 호출 할 수 있으며 번들이 업데이트됩니다. 이는 EnableOptimizations가 true 또는 false 일 때 모두 작동합니다. 즉, 디버그 또는 라이브 시나리오에서 올바른 마크 업이 다음과 같이 표시됩니다.
@Scripts.Render("~/bundles/your-bundle-virtual-path")
답변
또한 다시 빌드하지 않고 번들을 업데이트하는 데 문제가 발생했습니다. 이해해야 할 중요한 사항은 다음과 같습니다.
- 파일 경로가 변경되면 번들이 업데이트되지 않습니다.
- 번들의 가상 경로가 변경되면 번들이 업데이트됩니다.
- 디스크의 파일이 변경되면 번들이 업데이트됩니다.
따라서 동적 번들링을 수행하는 경우 번들의 가상 경로가 파일 경로를 기반으로하도록 코드를 작성할 수 있습니다. 파일 경로를 해시하고 해당 해시를 번들의 가상 경로 끝에 추가하는 것이 좋습니다. 이렇게하면 파일 경로가 변경 될 때 가상 경로도 변경되고 번들이 업데이트됩니다.
이 문제를 해결 한 코드는 다음과 같습니다.
public static IHtmlString RenderStyleBundle(string bundlePath, string[] filePaths)
{
// Add a hash of the files onto the path to ensure that the filepaths have not changed.
bundlePath = string.Format("{0}{1}", bundlePath, GetBundleHashForFiles(filePaths));
var bundleIsRegistered = BundleTable
.Bundles
.GetRegisteredBundles()
.Where(bundle => bundle.Path == bundlePath)
.Any();
if(!bundleIsRegistered)
{
var bundle = new StyleBundle(bundlePath);
bundle.Include(filePaths);
BundleTable.Bundles.Add(bundle);
}
return Styles.Render(bundlePath);
}
static string GetBundleHashForFiles(IEnumerable<string> filePaths)
{
// Create a unique hash for this set of files
var aggregatedPaths = filePaths.Aggregate((pathString, next) => pathString + next);
var Md5 = MD5.Create();
var encodedPaths = Encoding.UTF8.GetBytes(aggregatedPaths);
var hash = Md5.ComputeHash(encodedPaths);
var bundlePath = hash.Aggregate(string.Empty, (hashString, next) => string.Format("{0}{1:x2}", hashString, next));
return bundlePath;
}
답변
( StyleBundle 또는 ScriptBundle ) 에서 파생 하여 생성자에 포함을 추가하지 않은 다음 재정의 해 보셨습니까?
public override IEnumerable<System.IO.FileInfo> EnumerateFiles(BundleContext context)
동적 스타일 시트에 대해이 작업을 수행하고 EnumerateFiles는 모든 요청에 대해 호출됩니다. 아마도 가장 좋은 해결책은 아니지만 작동합니다.
답변
죽은 스레드를 되살리는 것에 대해 사과했지만 Umbraco 사이트에서 번들 캐싱과 비슷한 문제가 발생했습니다. 사용자가 백엔드에서 예쁜 버전을 변경하면 스타일 시트 / 스크립트가 자동으로 축소되도록했습니다.
내가 이미 가지고있는 코드는 (스타일 시트의 onSaved 메서드에 있음) :
BundleTable.Bundles.Add(new StyleBundle("~/bundles/styles.min.css").Include(
"~/css/main.css"
));
및 (onApplicationStarted) :
BundleTable.EnableOptimizations = true;
내가 무엇을 시도해도 “~ / bundles / styles.min.css”파일이 변경되지 않은 것 같습니다. 내 페이지의 머리 부분에서 나는 원래 다음과 같이 스타일 시트를로드하고있었습니다.
<link rel="stylesheet" href="~/bundles/styles.min.css" />
그러나 이것을 다음과 같이 변경하여 작동하게했습니다.
@Styles.Render("~/bundles/styles.min.css")
Styles.Render 메서드는 위에서 Hao가 설명한 캐시 키라고 생각하는 파일 이름 끝에 쿼리 문자열을 가져옵니다.
저에게는 그렇게 간단했습니다. 이것이 몇 시간 동안 인터넷 검색을하고 몇 년 된 게시물을 찾을 수 있었던 나와 같은 다른 사람에게 도움이되기를 바랍니다!