如何为Scripts.Render添加defer属性、为Styles.Render配置preload属性
脚本添加defer属性的正确实现
你之前使用的Scripts.RenderFormat仅在<compilation debug="false">(发布模式、Bundle开启打包)时生效,调试模式下Bundle会拆分输出原始文件,模板不会生效,以下是兼容所有模式的方案:
方案1:全局所有脚本自动加defer
在App_Start/BundleConfig.cs中自定义Bundle类型:
public class DeferScriptBundle : ScriptBundle { public DeferScriptBundle(string virtualPath) : base(virtualPath) { } public DeferScriptBundle(string virtualPath, string cdnPath) : base(virtualPath, cdnPath) { } public override IHtmlString Render(string[] paths) { return new HtmlString(base.Render(paths).ToHtmlString().Replace(">", " defer>")); } }
注册Bundle时替换原有ScriptBundle:
bundles.Add(new DeferScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));
视图中直接调用即可自动带defer属性:
@Scripts.Render("~/bundles/jquery")
方案2:单个脚本按需加defer
不需要修改全局配置,直接在视图中写:
@{ var scriptBundle = BundleTable.Bundles.GetBundleFor("~/bundles/jquery"); var context = new HttpContextWrapper(HttpContext.Current); foreach (var file in scriptBundle.EnumerateFiles(context, false)) { <script src="@Url.Content(file.IncludedVirtualPath)" defer></script> } }
样式配置preload的正确实现
preload需要同时输出预加载标签和样式生效标签,还要兼容禁用JS的场景:
方案1:全局所有样式自动加preload
在App_Start/BundleConfig.cs中自定义Bundle类型:
public class PreloadStyleBundle : StyleBundle { public PreloadStyleBundle(string virtualPath) : base(virtualPath) { } public PreloadStyleBundle(string virtualPath, string cdnPath) : base(virtualPath, cdnPath) { } public override IHtmlString Render(string[] paths) { var originalStyle = base.Render(paths).ToHtmlString(); var preloadStyle = originalStyle.Replace("rel=\"stylesheet\"", "rel=\"preload\" as=\"style\" onload=\"this.rel='stylesheet'\""); var noscriptFallback = $"<noscript>{originalStyle}</noscript>"; return new HtmlString(preloadStyle + Environment.NewLine + noscriptFallback); } }
注册Bundle时替换原有StyleBundle:
bundles.Add(new PreloadStyleBundle("~/Content/css").Include("~/Content/site.css"));
视图中直接调用即可自动生成preload配置:
@Styles.Render("~/Content/css")
方案2:单个样式按需加preload
直接在视图中写:
@{ var styleBundle = BundleTable.Bundles.GetBundleFor("~/Content/css"); var context = new HttpContextWrapper(HttpContext.Current); foreach (var file in styleBundle.EnumerateFiles(context, false)) { var href = Url.Content(file.IncludedVirtualPath); <link rel="preload" as="style" href="@href" onload="this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="@href"></noscript> } }
内容的提问来源于stack exchange,提问作者Prem Singh
相关产品推荐
相关产品推荐

