【问题标题】:How to make bundles unminify and list individual files when using a cookieless static content server?使用无 cookie 静态内容服务器时,如何使捆绑包取消缩小并列出单个文件?
【发布时间】:2025-11-28 03:10:01
【问题描述】:

我有两个 VS 项目,一个用于主网站,一个用于“静态内容”网站,其中所有 css、js、图像和其他静态内容都将通过无 cookie 域存储和访问。

所以我的静态站点中有一个 BundleConfig.cs,用于创建所有捆绑包:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/bundles/styles").IncludeDirectory("~/app/styles", "*.css", true));
        bundles.Add(new ScriptBundle("~/bundles/scripts").IncludeDirectory("~/app/src", "*.js", true));
    }
}

在主站点中,我有另一个 BundleConfig.cs,我将主站点指向静态内容站点,如下所示:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        var staticWebsite = ConfigurationManager.AppSettings["StaticWebsite"];
        var versionNumber = ConfigurationManager.AppSettings["VersionNumber"];

        Styles.DefaultTagFormat = string.Format("<link href='{0}{{0}}?v={1}' rel='stylesheet'/>", staticWebsite, versionNumber);
        Scripts.DefaultTagFormat = string.Format("<script src='{0}{{0}}?v={1}'></script>", staticWebsite, versionNumber);

    }
}

现在我可以使用像这样渲染的@Styles.Render("~/bundles/styles")@Scripts.Render("~/bundles/scripts"),这正是我想要的方式,而且效果很好:

<link href='http://mycookielessdomain.com/bundles/styles?v=1.0.0.0' rel='stylesheet'/>
<script src='http://mycookielessdomain.com/bundles/scripts?v=1.0.0.0'></script>

我遇到的问题是,无论debug=true 与否,内容都总是 被缩小和捆绑。即使我在两个 BundleConfig.cs 文件中都使用 BundleTable.EnableOptimization = false@Styles.Render()@Scripts.Render() 仍然只呈现一个标签并引用缩小的内容。

我知道主站点不知道捆绑在静态内容站点中的各个文件,但我希望有一些方法可以在主站点的 BundleConfig 中手动指定这些路径,以便 Render( ) 方法可以在优化关闭时单独列出它们......如果我能让它们关闭,那就是。

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-4 bundling-and-minification system.web.optimization


    【解决方案1】:

    因此,我能够通过添加自定义 VirtualPathProvider 来实现此功能,它使主项目在静态内容项目中搜索单个文件。在调试模式下,文件将单独列出。在 RELEASE 模式下,将改为引用缩小的捆绑包。

    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            var staticWebsite = ConfigurationManager.AppSettings["StaticWebsite"];
            var versionNumber = ConfigurationManager.AppSettings["VersionNumber"];
    
            Styles.DefaultTagFormat = string.Format("<link href='{0}{{0}}?v={1}' rel='stylesheet'/>", staticWebsite, versionNumber);
            Scripts.DefaultTagFormat = string.Format("<script src='{0}{{0}}?v={1}'></script>", staticWebsite, versionNumber);
    
    #if DEBUG
            // Includes files from the static content project so they can be listed individually if in DEBUG mode.
            BundleTable.VirtualPathProvider = new StaticContentVirtualPathProvider();
            bundles.Add(new StyleBundle("~/bundles/styles").IncludeDirectory("~/app/styles", "*.css", true));
            bundles.Add(new ScriptBundle("~/bundles/scripts").IncludeDirectory("~/app/src", "*.js", true));
    #endif
        }
    }
    

    这是我的自定义 VirtualPathProvider:

    public class StaticContentVirtualPathProvider : VirtualPathProvider
    {
        // Modify this to be the relative path from your main project to your static content project.
        private const string StaticContentRelativePath = @"..\..\MyStaticContentProjectFolder";
    
        public static string GetStaticContentPath(string virtualPath, bool isDirectory = false)
        {
            virtualPath = virtualPath.Replace('/', '\\').Replace("~", "");
    
            if (isDirectory && !virtualPath.EndsWith("\\")) virtualPath += "\\";
    
            return HttpRuntime.AppDomainAppPath + StaticContentRelativePath + virtualPath;
        }
    
        public override bool FileExists(string virtualPath)
        {
            return File.Exists(GetStaticContentPath(virtualPath));
        }
    
        public override bool DirectoryExists(string virtualDir)
        {
            return Directory.Exists(GetStaticContentPath(virtualDir));
        }
    
        public override VirtualFile GetFile(string virtualPath)
        {
            return new StaticContentVirtualFile(virtualPath);
        }
    
        public override VirtualDirectory GetDirectory(string virtualDir)
        {
            return new StaticContentVirtualDirectory(virtualDir);
        }
    
        private class StaticContentVirtualFile : VirtualFile
        {
            public StaticContentVirtualFile(string virtualPath)
                : base(virtualPath)
            {
                this.virtualPath = virtualPath;
            }
    
            private readonly string virtualPath;
    
            public override Stream Open()
            {
                return new FileStream(StaticContentVirtualPathProvider.GetStaticContentPath(virtualPath), FileMode.Open);
            }
        }
    
        internal class StaticContentVirtualDirectory : VirtualDirectory
        {
            public StaticContentVirtualDirectory(string virtualPath)
                : base(virtualPath)
            {
            }
    
            public override IEnumerable Files
            {
                get
                {
                    var filePaths = Directory.GetFiles(GetStaticContentPath(this.VirtualPath, true));
                    var files = filePaths.Select(filePath => new StaticContentVirtualFile(this.VirtualPath + Path.GetFileName(filePath))).ToList();
                    return files;
                }
            }
    
            public override IEnumerable Directories
            {
                get
                {
                    var subDirectoryPaths = Directory.GetDirectories(GetStaticContentPath(this.VirtualPath, true));
                    var dirs = subDirectoryPaths.Select(subDirectoryPath => new StaticContentVirtualDirectory(this.VirtualPath + Path.GetFileName(subDirectoryPath))).ToList();
                    return dirs;
                }
            }
    
            public override IEnumerable Children { get { throw new NotImplementedException(); } }
        }
    }
    

    【讨论】:

      【解决方案2】:

      BundleTable.EnableOptimization = "false" 不是在这里播放的事件,因为您的主站点正在引用“捆绑包”,无论调试状态或 EnableOptimization 如何,它总是会被捆绑和缩小。

      因此,静态站点上的 @Styles.Render("~/bundles/styles") 将在 BundleTable.EnableOptimization = "false" 时呈现单个文件,但如果您直接导航到 /bundles/styles,您仍然会获得缩小的捆绑包(您在主站点上执行的操作)。

      一个选项(也许是您唯一的选择)是在静态站点上配置捆绑器,以便在 BundleTable.EnableOptimization = "false" 时不缩小捆绑包。这可以通过编写一个继承自Bundle 并使用它自己的自定义IBundleBuilder 的类来完成(您甚至可以在将每个文件添加到包中时将文件名写为注释)。一些为您指明正确方向的示例代码可以be found on GitHub

      【讨论】:

      • 谢谢,这是有道理的。在调试模式下,我可以通过使用new Bundle() 而不是new ScriptBundle() 来使其不缩小,但我也希望单独列出文件,这样我就不必每次制作时都重新构建包JS 变化。我发布了一个允许我这样做的答案。
      最近更新 更多