브라우저가 asp.net 응용 프로그램에서 최신 js 및 css 파일을 가져오도록 합니다.
일부 브라우저는 js 및 css 파일을 캐시하여 강제로 새로 고치지 않으면 새로 고치지 못합니다.가장 쉬운 방법은 무엇입니까?
저는 효과가 있을 것 같은 이 솔루션을 구현했습니다.
페이지에서 버전 변수 선언
public string version { get; set; }
web.config 키에서 버전 번호 가져오기
version = ConfigurationManager.AppSettings["versionNumber"];
당신의 aspx 페이지에서 Javascript와 스타일시트에 그렇게 전화를 겁니다.
<script src="scripts/myjavascript.js?v=<%=version %>" type="text/javascript"></script>
<link href="styles/mystyle.css?v=<%=version %>" rel="stylesheet" type="text/css" />
따라서 web.config에서 버전 = 1.1을 1.0에서 설정하면 브라우저가 최신 파일을 다운로드하여 사용자와 사용자의 불만을 덜어줄 것입니다.
더 잘 작동하는 다른 솔루션이 있습니까? 아니면 웹 사이트에 예기치 않은 문제를 일으킬 수 있습니까?
마지막으로 수정된 타임스탬프를 쿼리 매개 변수로 스크립트에 적용하여 이 문제를 해결했습니다.
저는 이것을 확장 방법으로 했고, 제 CSHTML 파일에 사용했습니다.참고: 이 구현은 디스크를 너무 많이 스레싱하지 않도록 타임스탬프를 1분 동안 캐시합니다.
확장 방법은 다음과 같습니다.
public static class JavascriptExtension {
public static MvcHtmlString IncludeVersionedJs(this HtmlHelper helper, string filename) {
string version = GetVersion(helper, filename);
return MvcHtmlString.Create("<script type='text/javascript' src='" + filename + version + "'></script>");
}
private static string GetVersion(this HtmlHelper helper, string filename)
{
var context = helper.ViewContext.RequestContext.HttpContext;
if (context.Cache[filename] == null)
{
var physicalPath = context.Server.MapPath(filename);
var version = $"?v={new System.IO.FileInfo(physicalPath).LastWriteTime.ToString("MMddHHmmss")}";
context.Cache.Add(filename, version, null,
DateTime.Now.AddMinutes(5), TimeSpan.Zero,
CacheItemPriority.Normal, null);
return version;
}
else
{
return context.Cache[filename] as string;
}
}
}
그런 다음 CSHTML 페이지에서 다음 작업을 수행합니다.
@Html.IncludeVersionedJs("/MyJavascriptFile.js")
렌더링된 HTML에서는 다음과 같이 표시됩니다.
<script type='text/javascript' src='/MyJavascriptFile.js?20111129120000'></script>
ASP.NET Core(MVC 6)에서 이 기능은 다음을 통해 즉시 작동합니다.asp-append-version
태그 도우미:
<script src="scripts/myjavascript.js" asp-append-version="true"></script>
<link href="styles/mystyle.css rel="stylesheet" asp-append-version="true" />
솔루션이 작동합니다.사실 그것은 꽤 인기가 있습니다.
스택 오버플로도 유사한 방법을 사용합니다.
<link rel="stylesheet" href="http://sstatic.net/so/all.css?v=6184">
어디에v=6184
SVN 리비전 번호일 것입니다.
JS/CSS에 번들을 사용하는 경우 ASP.NET MVC가 이 작업을 대신 처리합니다.번들에 GUID 형식의 버전 번호가 자동으로 추가되고 번들이 업데이트될 때만 이 GUID가 업데이트됩니다(소스 파일에 변경 사항이 있음).
이는 콘텐츠 로드 시간을 크게 향상시킬 수 있기 때문에 JS/CSS 파일이 많은 경우에도 도움이 됩니다!
asp.net 에는 번들링이라는 기본 제공 방법이 있습니다.그냥 쓰세요.새 버전마다 고유 접미사 "?v=XXXXXXX"가 붙습니다.디버깅 모드에서는 web.config의 make 설정을 켜기 위해 번들링이 꺼집니다.
<system.web>
<compilation debug="false" />
</system.web>
또는 RegisterBundle(BundleCollection 번들) 메서드에 다음을 추가합니다.
BundleTable.EnableOptimizations = true;
예:
BundleConfig.cs :
bundles.Add(new ScriptBundle("~/Scripts/myjavascript.js")
.Include("~/Scripts/myjavascript.js"));
bundles.Add(new StyleBundle("~/Content/mystyle.css")
.Include("~/Content/mystyle.css"));
_Layout.cshtml :
@Scripts.Render("~/Scripts/myjavascript.js")
@Styles.Render("~/Content/mystyle.css")
캐시를 부수기 위해 경로를 고유하게 만드는 간단한 라이너가 필요했습니다.이것은 저에게 효과가 있었습니다.
<script src="scripts/main.js?bust_js_cache=<%=System.IO.File.GetLastWriteTime(Server.MapPath("scripts/main.js")).ToString("HH:mm:ss")%>" type="text/javascript"></script>
파일이 페이지에 마지막으로 로드된 이후로 수정된 경우 브라우저는 업데이트된 파일을 풀합니다.
을 생성합니다.last modified
을 찍다.js
파일을 저장하고 접근이 쉽지 않을 수 있는 버전 대신에 파일을 저장합니다.
<script src="scripts/main.js?bust_js_cache=10:18:38" type="text/javascript"></script>
다른 옵션은 파일의 체크섬을 가져오는 것일 수 있습니다.
이에 대한 답은 질문의 op가 제시한 답보다 더 간단합니다(접근법은 동일합니다).
web.config에서 키를 정의합니다.
<add key="VersionNumber" value="06032014"/>
aspx 페이지에서 app 설정으로 직접 전화 걸기:
<link href="styles/navigation.css?v=<%=ConfigurationManager.AppSettings["VersionNumber"]%>" rel="stylesheet" type="text/css" />
Adam Tegan의 답변을 기반으로 웹 양식 응용 프로그램에서 사용하도록 수정되었습니다.
.cs 클래스 코드에서:
public static class FileUtility
{
public static string SetJsVersion(HttpContext context, string filename) {
string version = GetJsFileVersion(context, filename);
return filename + version;
}
private static string GetJsFileVersion(HttpContext context, string filename)
{
if (context.Cache[filename] == null)
{
string filePhysicalPath = context.Server.MapPath(filename);
string version = "?v=" + GetFileLastModifiedDateTime(context, filePhysicalPath, "yyyyMMddhhmmss");
return version;
}
else
{
return string.Empty;
}
}
public static string GetFileLastModifiedDateTime(HttpContext context, string filePath, string dateFormat)
{
return new System.IO.FileInfo(filePath).LastWriteTime.ToString(dateFormat);
}
}
aspx 마크업에서:
<script type="text/javascript" src='<%= FileUtility.SetJsVersion(Context,"/js/exampleJavaScriptFile.js") %>'></script>
그리고 렌더링된 HTML에서 다음과 같이 나타납니다.
<script type="text/javascript" src='/js/exampleJavaScriptFile.js?v=20150402021544'></script>
다음은 ASP.NET 5 / MVC 6 / vNext에서 작동하는 접근 방식입니다.
1단계: 이 스레드의 다른 답변과 유사하게 파일의 마지막 쓰기 시간을 반환하는 클래스를 만듭니다.이 경우 ASP.NET 5(또는 기타) 종속성 주입이 필요합니다.
public class FileVersionService
{
private IHostingEnvironment _hostingEnvironment;
public FileVersionService(IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
public string GetFileVersion(string filename)
{
var path = string.Format("{0}{1}", _hostingEnvironment.WebRootPath, filename);
var fileInfo = new FileInfo(path);
var version = fileInfo.LastWriteTimeUtc.ToString("yyyyMMddhhmmssfff");
return version;
}
}
2단계: startup.cs 에 주입할 서비스를 등록합니다.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<FileVersionService>();
...
}
3단계: 그런 다음 ASP.NET 5에서 다음과 같이 _Layout.cshtml과 같은 레이아웃 보기에 서비스를 직접 주입할 수 있습니다.
@inject Namespace.Here.FileVersionService fileVersionService
<!DOCTYPE html>
<html lang="en" class="@ViewBag.HtmlClass">
<head>
...
<link href="/css/styles.css?v=@fileVersionService.GetFileVersion("\\css\\styles.css")" rel="stylesheet" />
...
</head>
<body>
...
</body>
물리적 경로를 더 잘 결합하고 구문과 더 일치하는 스타일로 파일 이름을 처리하기 위해 몇 가지 마무리 작업을 수행할 수 있지만, 이것이 시작점입니다.ASP.NET 5로 이동하는 사람들에게 도움이 되길 바랍니다.
흥미롭게도 이 사이트는 페일 세이프여야 하지만 일부 프록시 설정과 관련하여 설명한 접근 방식에 문제가 있습니다.
이 메타 스택 오버플로 토론을 확인하십시오.
따라서 이를 고려할 때 GET 매개 변수를 사용하여 업데이트하지 않고 실제 파일 이름을 사용하는 것이 합리적일 수 있습니다.
href="/css/scriptname/versionNumber.css"
파일을 실제로 생성하거나 URL을 다시 작성해야 하기 때문에 이 작업이 더 많은 작업임에도 불구하고,
저는 제 aspnet MVC 4 사이트에서 약간 다른 기술을 사용했습니다.
_ViewStart.cshtml:
@using System.Web.Caching
@using System.Web.Hosting
@{
Layout = "~/Views/Shared/_Layout.cshtml";
PageData.Add("scriptFormat", string.Format("<script src=\"{{0}}?_={0}\"></script>", GetDeployTicks()));
}
@functions
{
private static string GetDeployTicks()
{
const string cacheKey = "DeployTicks";
var returnValue = HttpRuntime.Cache[cacheKey] as string;
if (null == returnValue)
{
var absolute = HostingEnvironment.MapPath("~/Web.config");
returnValue = File.GetLastWriteTime(absolute).Ticks.ToString();
HttpRuntime.Cache.Insert(cacheKey, returnValue, new CacheDependency(absolute));
}
return returnValue;
}
}
그러면 실제 보기에서:
@Scripts.RenderFormat(PageData["scriptFormat"], "~/Scripts/Search/javascriptFile.min.js")
위의 답변에서 시작하여 저는 도우미가 CSS 파일에서도 작동하도록 코드를 약간 수정했고 빌드를 할 때뿐만 아니라 파일에서 약간의 변경을 할 때마다 버전을 추가했습니다.
public static class HtmlHelperExtensions
{
public static MvcHtmlString IncludeVersionedJs(this HtmlHelper helper, string filename)
{
string version = GetVersion(helper, filename);
return MvcHtmlString.Create("<script type='text/javascript' src='" + filename + version + "'></script>");
}
public static MvcHtmlString IncludeVersionedCss(this HtmlHelper helper, string filename)
{
string version = GetVersion(helper, filename);
return MvcHtmlString.Create("<link href='" + filename + version + "' type ='text/css' rel='stylesheet'/>");
}
private static string GetVersion(this HtmlHelper helper, string filename)
{
var context = helper.ViewContext.RequestContext.HttpContext;
var physicalPath = context.Server.MapPath(filename);
var version = "?v=" +
new System.IO.FileInfo(physicalPath).LastWriteTime
.ToString("yyyyMMddHHmmss");
context.Cache.Add(physicalPath, version, null,
DateTime.Now.AddMinutes(1), TimeSpan.Zero,
CacheItemPriority.Normal, null);
if (context.Cache[filename] == null)
{
context.Cache[filename] = version;
return version;
}
else
{
if (version != context.Cache[filename].ToString())
{
context.Cache[filename] = version;
return version;
}
return context.Cache[filename] as string;
}
}
}
<?php $rand_no = rand(10000000, 99999999)?> <script src="scripts/myjavascript.js?v=<?=$rand_no"></script>
이것은 모든 브라우저에서 작동합니다.여기서 저는 PHP를 사용하여 임의의 no를 생성했습니다.자신의 서버 사이드 언어를 사용할 수 있습니다.`
아래 표시된 대로 파일 수정 시간 가져오기
private static string GetLastWriteTimeForFile(string pathVal)
{
return System.IO.File.GetLastWriteTime(HostingEnvironment.MapPath(pathVal)).ToFileTime().ToString();
}
입력을 쿼리 문자열로 추가합니다.
public static string AppendDateInFile(string pathVal)
{
var patheWithDate = new StringBuilder(pathVal);
patheWithDate.AppendFormat("{0}x={1}",
pathVal.IndexOf('?') >= 0 ? '&' : '?',
GetLastWriteTimeForFile(pathVal));
return patheWithDate.ToString();
}
마크업에서 호출합니다.
MVC 확장 도우미 접근법
확장 메서드 추가
namespace TNS.Portal.Helpers
{
public static class ScriptExtensions
{
public static HtmlString QueryStringScript<T>(this HtmlHelper<T> html, string path)
{
var file = html.ViewContext.HttpContext.Server.MapPath(path);
DateTime lastModified = File.GetLastWriteTime(file);
TagBuilder builder = new TagBuilder("script");
builder.Attributes["src"] = path + "?modified=" + lastModified.ToString("yyyyMMddhhmmss");
return new HtmlString(builder.ToString());
}
public static HtmlString QueryStringStylesheet<T>(this HtmlHelper<T> html, string path)
{
var file = html.ViewContext.HttpContext.Server.MapPath(path);
DateTime lastModified = File.GetLastWriteTime(file);
TagBuilder builder = new TagBuilder("link");
builder.Attributes["href"] = path + "?modified=" + lastModified.ToString("yyyyMMddhhmmss");
builder.Attributes["rel"] = "stylesheet";
return new HtmlString(builder.ToString());
}
}
}
web.config에 이 네임스페이스를 추가
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="TNS.Portal" />
<add namespace="TNS.Portal.Helpers" />
</namespaces>
</pages>
</system.web.webPages.razor>
보기에서 다음과 같이 사용
@Html.QueryStringScript("/Scripts/NPIAjaxCalls.js")
@Html.QueryStringStylesheet("/Content/StyledRadio.css")
.NET Web Forms 개발자를 위한 간단한 사전 제안 및 코드 제공.
리소스에 대한 파일 경로의 상대 URL("~/")과 절대 URL을 모두 허용합니다.
다음과 같은 정적 확장명 클래스 파일을 넣습니다.
public static string VersionedContent(this HttpContext httpContext, string virtualFilePath)
{
var physicalFilePath = httpContext.Server.MapPath(virtualFilePath);
if (httpContext.Cache[physicalFilePath] == null)
{
httpContext.Cache[physicalFilePath] = ((Page)httpContext.CurrentHandler).ResolveUrl(virtualFilePath) + (virtualFilePath.Contains("?") ? "&" : "?") + "v=" + File.GetLastWriteTime(physicalFilePath).ToString("yyyyMMddHHmmss");
}
return (string)httpContext.Cache[physicalFilePath];
}
그런 다음 마스터 페이지에서 다음과 같이 호출합니다.
<link type="text/css" rel="stylesheet" href="<%= Context.VersionedContent("~/styles/mystyle.css") %>" />
<script type="text/javascript" src="<%= Context.VersionedContent("~/scripts/myjavascript.js") %>"></script>
이런 식으로 하는 것의 주된 문제는 주로 당신이 당신의 css 또는 js 파일을 변경할 때마다 당신의 코드에서 당신의 버전 번호를 업데이트하는 것을 기억해야 한다는 것입니다.
더 나은 방법은 다음과 같이 각 CSS 또는 Js 파일에 보장된 고유 매개 변수를 설정하는 것입니다.
<script src="scripts/myjavascript.js?_=<%=DateTime.Now.Ticks%>" type="text/javascript"></script>
<link href="styles/mystyle.css?_=<%=DateTime.Now.Ticks%>" rel="stylesheet" type="text/css" />
이렇게 하면 매번 서버에서 파일을 요청해야 합니다. 즉, 사이트는 페이지 로드 시 캐시되지 않고 매번 불필요한 대역폭을 사용하기 때문에 성능이 저하됩니다.
기본적으로 변경할 때마다 버전 번호를 업데이트하는 것을 기억할 수 있다면 변경 방법에서 벗어날 수 있습니다.
위의 답변을 바탕으로 CSS와 JS 파일로 작업할 수 있는 작은 확장 클래스를 작성했습니다.
public static class TimestampedContentExtensions
{
public static string VersionedContent(this UrlHelper helper, string contentPath)
{
var context = helper.RequestContext.HttpContext;
if (context.Cache[contentPath] == null)
{
var physicalPath = context.Server.MapPath(contentPath);
var version = @"v=" + new FileInfo(physicalPath).LastWriteTime.ToString(@"yyyyMMddHHmmss");
var translatedContentPath = helper.Content(contentPath);
var versionedContentPath =
contentPath.Contains(@"?")
? translatedContentPath + @"&" + version
: translatedContentPath + @"?" + version;
context.Cache.Add(physicalPath, version, null, DateTime.Now.AddMinutes(1), TimeSpan.Zero,
CacheItemPriority.Normal, null);
context.Cache[contentPath] = versionedContentPath;
return versionedContentPath;
}
else
{
return context.Cache[contentPath] as string;
}
}
}
다음과 같은 것을 쓰는 대신:
<link href="@Url.Content(@"~/Content/bootstrap.min.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content(@"~/Scripts/bootstrap.min.js")"></script>
이제 다음을 쓸 수 있습니다.
<link href="@Url.VersionedContent(@"~/Content/bootstrap.min.css")" rel="stylesheet" type="text/css" />
<script src="@Url.VersionedContent(@"~/Scripts/bootstrap.min.js")"></script>
즉, 간단히 교체할 수 있습니다.Url.Content
와 함께Url.VersionedContent
.
생성된 URL은 다음과 같습니다.
<link href="/Content/bootstrap.min.css?v=20151104105858" rel="stylesheet" type="text/css" />
<script src="/Scripts/bootstrap.min.js?v=20151029213517"></script>
할 수 .MapPath
안 요, 통가작않습다니지하동화▁since.contentPath
실제 파일이 아닙니다.
저는 각 페이지를 수정하지 않고 당신이 하고 있는 것과 비슷한 방법을 사용합니다.PreRender 이벤트가 마스터 파일로 추가되었습니다.그것은 내 논리를 한 곳에 유지하고 js와 css 파일 모두에 적용할 수 있습니다.
protected void Page_PreRender(object sender, EventArgs e)
{
HtmlLink link = null;
LiteralControl script = null;
foreach (Control c in Header.Controls)
{
//StyleSheet add version
if (c is HtmlLink)
{
link = c as HtmlLink;
if (link.Href.EndsWith(".css", StringComparison.InvariantCultureIgnoreCase))
{
link.Href += string.Format("?v={0}", ConfigurationManager.AppSettings["agVersion"]);
}
}
//Js add version
if (c is LiteralControl)
{
script = c as LiteralControl;
if (script.Text.Contains(".js"))
{
var foundIndexes = new List<int>();
for (int i = script.Text.IndexOf(".js\""); i > -1; i = script.Text.IndexOf(".js\"", i + 1))
{
foundIndexes.Add(i);
}
for (int i = foundIndexes.Count - 1; i >= 0; i--)
{
script.Text = script.Text.Insert(foundIndexes[i] + 3, string.Format("?v={0}", ConfigurationManager.AppSettings["agVersion"]));
}
}
}
}
}
스크립트 또는 스타일의 DefaultTagFormat 속성을 재정의할 수 있습니다.
Scripts.DefaultTagFormat = @"<script src=""{0}?v=" + ConfigurationManager.AppSettings["pubversion"] + @"""></script>";
Styles.DefaultTagFormat = @"<link href=""{0}?v=" + ConfigurationManager.AppSettings["pubversion"] + @""" rel=""stylesheet""/>";
ASP.Net Ajax 애플리케이션에서 이 문제를 해결하기 위해 내선번호를 생성한 다음 마스터 페이지를 호출했습니다.
자세한 내용은 링크를 통해 확인하실 수 있습니다.
아래의 개념에 의해 .net 응용 프로그램에서 CSS 버전 관리를 구현하는 쉽고 똑똑한 방법.백엔드 코드를 쓸 필요가 없습니다.
<link href="<%="../../App_Themes/Base/css/main.css?v="+ DateTime.Now.ToString("yyyyMMddhhmmss") +""%>" rel="stylesheet" />
ASP.NET 페이지의 경우 다음을 사용합니다.
전에
<script src="/Scripts/pages/common.js" type="text/javascript"></script>
AFTER(강제 재로드)
<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>
날짜 시간을 추가하는 중입니다.이제, 틱은 아주 잘 작동합니다.
그냥 이것을 내부 시스템에 넣으십시오.web.config의 웹 서버
<caching enabled="true" enableKernelCache="true">
<profiles>
<add extension=".html" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
<add extension=".css" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
<add extension=".js" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
</profiles>
</caching>
언급URL : https://stackoverflow.com/questions/2185872/force-browsers-to-get-latest-js-and-css-files-in-asp-net-application
'programing' 카테고리의 다른 글
Mongoose 자동 증분 (0) | 2023.05.18 |
---|---|
git 저장소에서 암호를 처리하는 가장 좋은 방법은 무엇입니까? (0) | 2023.05.18 |
충돌하는 Gitrebase의 중간에서 "그들의" 변화를 얻는 방법은 무엇입니까? (0) | 2023.05.18 |
angular2의 입력을 비활성화하는 방법 (0) | 2023.05.13 |
새 리포지토리에 대해 https가 아닌 ssh로 기본 설정하려면 어떻게 해야 합니까? (0) | 2023.05.13 |