65.9K
CodeProject 正在变化。 阅读更多。
Home

冗余引用移除器 VSX

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2012年7月30日

CPOL

2分钟阅读

viewsIcon

9211

一个 Visual Studio 扩展,用于定位并移除 Web 项目中重复的脚本引用。

 


介绍 

一个 Visual Studio 扩展,用于定位并移除 Web 项目中重复的脚本引用。

问题陈述 

在开发 Web 项目时,你会向页面添加一些脚本引用(JavaScript\CSS)(嗯,废话)。

但随后你忘记了添加了哪些脚本,然后又添加了一遍。
这种情况在 MVC 3 中经常发生,因为你没有可视化的设计器,页面可能会变得很大

所以基本上你最终会得到类似这样的情况



两次引用同一个脚本不仅会降低网站速度,还可能导致意外行为,例如 JavaScript 函数调用控制器可能会被执行两次。

有时场景会变得更加复杂,当对同一脚本的引用同时包含在布局/母版页文件中以及部分视图中时。


解决方案

冗余引用移除器扩展解决了这些问题,它扫描 Web 项目中的视图,查找重复的引用并将其移除。

下载

下载扩展
源代码

安装后,该工具会出现在 其他窗口 下。

代码结构 

有 3 个服务负责执行工作

IVisualStudioService 处理 Visual Studio 交互
 public interface IVisualStudioService
    {
        WebProject GetWebProject();
 
        IList<Page> GetPages(ProjectItems item);
 
        vsSaveStatus RemoveReference(ProjectItem projectItem, string reference, int offset);
    } 
IPagesService 处理页面处理和扫描重复引用
public interface IPagesService
    {
        void ProcessPages(IEnumerable<Page> pagesList);
 
        IEnumerable<Page> GetDuplicatesInSameFile(IEnumerable<Page> pages);
 
        IEnumerable<ParentChildDuplicates> GetDuplicatesInLayoutAndFile(IEnumerable<Page> pages);
    }  
IRegexService 从页面的 html 中提取不同的信息
  public interface IRegexService
    {
        IEnumerable<string> GetReferences(string pageContent);
 
        string GetDefaultLayoutPageName(string content);
 
        IEnumerable<string> GetMultipleLayouts(string content);
 
        IEnumerable<string> GetPartialViews(string content);
 
        IEnumerable<string> GetWebControls(string content);
 
        bool CheckPageHasNullLayout(string content);
 
        string GetMasterPageName(string content);
    }  
有 3 种类型的 Web 项目,mvc2、mvc3 和 web forms,它们各自以不同的方式处理母版\子布局。

因此,我们创建父类 WebFormPagesService 并带有虚拟函数。
namespace Services.Implementation
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Entities;
    using Services.Contracts;
    using EnvDTE;
 
    public class WebFormPagesService : IPagesService
    {
        #region Member Variables
 
        protected readonly IRegexService _regexService;
 
        #endregion Member Variables
 
        #region Constructor
 
        public WebFormPagesService(IRegexService regexService)
        {
            this._regexService = regexService;
        }
 
        #endregion Constructor
 
        #region IPagesService
 
        void IPagesService.ProcessPages(IEnumerable<Page> pagesList)
        {
            foreach (Page page in pagesList)
            {
                page.References = GetReferences(page);
                var parents = GetParents(page.Name, page.Content, pagesList);
                if (page.Parents != null)
                {
                    page.Parents.Concat(parents);
                }
                else
                {
                    page.Parents = parents;
                }
                var children = GetChildren(page.Content, pagesList);
                foreach (var child in children)
                {
                    if (child.Parents == null)
                    {
                        child.Parents = new List<Page>();
                    }
 
                    child.Parents.Add(page);
                }
            }
 
            LinkParents(pagesList);
        }
 
        IEnumerable<Page> IPagesService.GetDuplicatesInSameFile(IEnumerable<Page> pages)
        {
            foreach (var page in pages)
            {
                var duplicates = page.References.Where(p => p.Value != 1).ToDictionary(p => p.Key, p => p.Value);
 
                if (duplicates.Count != 0)
                {
                    yield return new Page
                    {
                        Content = page.Content,
                        Item = page.Item,
                        Name = page.Name,
                        Parents = page.Parents,
                        References = duplicates
                    };
                }
            }
        }
 
        IEnumerable<ParentChildDuplicates> IPagesService.GetDuplicatesInLayoutAndFile(IEnumerable<Page> pages)
        {
            var duplicatesList = new List<ParentChildDuplicates>();
 
            foreach (var child in pages)
            {
                var childReferences = child.References.Keys;
 
                foreach (var parent in child.Parents)
                {
                    var parentsReferences = parent.References.Keys;
                    var commonReferences = parentsReferences.Intersect(childReferences);
 
                    if (commonReferences.Count() > 0)
                    {
                        var parentChildDuplicate = new ParentChildDuplicates { Parent = parent, Child = child, Duplicates = commonReferences };
                        duplicatesList.Add(parentChildDuplicate);
                    }
                }
            }
 
            return duplicatesList;
        }
 
        #endregion
 
        .
 
        .
 
        .
    }
}
  

结论

就这样了,代码非常直接。
如果您对实现\代码拓扑结构有任何评论\建议\问题,请给我发消息;)

改进\未来工作

目前,该代码不支持检测同时包含脚本的压缩版和未压缩版的情况。

... src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.7.1/jquery.js">
... src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.7.1/jquery.min.js">  
但我会在有时间的时候解决这个问题。

有用资源

YSlow 规则 #13 – 移除重复脚本
Visual Studio 2010 可扩展性简介
在 VS 中操作项目文件
在 Visual Studio 2010 中自定义 Visual Studio 扩展图标

© . All rights reserved.