【问题标题】:Single Codebase multiple websites单个代码库多个网站
【发布时间】:2009-10-07 08:32:14
【问题描述】:

我们开发了一个使用单一代码库的系统,由四个 Visual Studio 项目组成,一个管理网站和一个面向客户的网站(每个系统都有自己的 MS SQL 数据库)。

效果很好,因为所有新网站(包括管理员)都从 SVN 中引用相同的代码库项目,因此对代码库所做的任何更改都可以用于所有网站。

每个网站都有不同的母版页和不同的用户控件 (.ascx),因此虽然网站背后的主要编码相同,但部分不同。

我们现在遇到的问题是,如果存在错误、功能更改或新功能,我们必须在所有站点中分别实施(对于管理员站点和客户站点)。这开始让我们发疯,也意味着我们在实施更改时有很大的误差范围。

我曾考虑过使用 svn:externals 但这会变得很乱。

可以选择从主网站和主管理系统分支,但合并以获取新代码是一个主要问题,因为网站不完全相同。

我认为一个很好的概述是每个站点的标记完全不同(除了管理站点,这只是一个主题更改),但代码库是相同的。

管理这个问题的最佳方法是什么,或者我们是否被困在做大量的复制和粘贴?

编辑

您希望明确哪些要点?

出现的问题包括页面 JavaScript 不同,HTML 布局在网站之间可能完全不同。但是页面的代码是一样的。

所以我需要“同步”文件和文件夹,例如在 app_code 中找到的文件和文件夹,但这里也存在问题。

站点 1 和站点 2 可能完全相同,只是主题不同。 站点 3 也有不同的主题,但它也有一些仅本站点需要的定制代码,app_code 中的一些代码也与站点 1 和站点 2 不同

现在我可以通过分支轻松实现这一点,但是在合并到新分支时,如果存在代码差异,则会出现重大冲突。

合并也将成为一项大型任务并且耗时太长,因为我们只需要合并某些文件夹和文件,尽管您无法通过分支合并单个文件(这可能是错误的)。

例如:

在根目录中有一个download.aspx,它返回一个流作为响应而不是一个页面,用于通过系统推送所有下载请求。

所以站点 1 和站点 2 中的这个页面是相同的,但是站点 3 中它做了一些其他站点不需要或不需要的额外操作。

我们不希望这个定制功能超载,因为我们不希望/不需要它用于其他网站,我们现在不能再从主网站合并这个文件,它必须手动合并。

希望这能更好地解释我想要实现的目标。

编辑 2

网站基本结构

|- App_code
|- App_Themes
|- Bin
|- Content
|     |- Flash
|     |- Images
|     |- Scripts
|     |- Uploaded
|
|- Controls
|     |- MasterPage
|     |     |-MasterPageControls
|     |
|     |- Navigation
|     |- Search
|     |- Templates
|     |     |- Control Templates 
|     |     |- Page Templates
|     |
|     |- WebServices
|     
|- Errors
|

Controls Navigation、Search、Templates 下的所有内容都是 .ascx 文件。

在根目录下有几个文件,包括default.aspx、download.aspx和preview.aspx

这些是网站的主要页面(忽略错误页面),所有页面都是从数据库动态创建的。

Controls 文件夹是网站之间的大部分更改发生在 MasterPage 以及所有其他用户控件中的位置。

【问题讨论】:

  • 很有趣,看看 Jeff Atwood 是否就他们如何使用 stackoverflow 解决这个确切问题发表意见,我不知道以前在任何地方都讨论过这个问题。
  • 为简洁起见,请原发帖者尝试澄清和编辑?
  • 这是个好问题

标签: version-control


【解决方案1】:

几个月前,当我们开始对我们的网络应用程序进行重大重写时,我遇到了这个确切的问题。我们有两个不同版本的几乎相同的站点。后端代码 99% 相同,而 JavaScript、CSS 和其他前端代码则大不相同。我们将这两个站点放在同一个 SVN 存储库中的不同主干中,很快就变成了在它们之间复制和粘贴公共代码的噩梦。由于文件的细微变化,修补和合并太痛苦而无用。

我们的解决方案既不是 SVN 相关的,也不是构建公共库。相反,独立站点的概念是通过多个配置文件和 CSS、图像和语言资源文件的层次结构在单个代码库中定义的。特定于站点的功能由配置值启用。

每个站点都有一个唯一的名称(例如“foo”和“bar”),该名称是在运行时从 Web.config 文件中检索的。该名称用于确定加载哪个配置文件以及使用哪些客户端文件。该设置在 SVN 中为空白。它是由我们的部署脚本在复制到 Web 服务器时设置的。在我们的本地开发机器上,环境变量定义了我们要使用的站点。

站点特定文件的文件结构如下所示:

|- Config
|     |- AppSettings.foo.config      <- overrides Web.config AppSettings for "foo" site
|     |- AppSettings.bar.config      <- overrides Web.config AppSettings for "bar" site
|- Content
|     |- CSS
|          |- main.css               <- default CSS file for all sites
|          |- main.foo.css           <- CSS overrides for "foo" site
|     |- Images
|          |- logo.jpg               <- default logo
|          |- logo.foo.jpg           <- logo used if site name is "foo"
|          |- logo.bar.jpg           <- logo used if site name is "bar"

到目前为止,这对我们来说效果很好。向特定站点添加新功能就像将功能添加到我们的代码库一样简单,并且只为该站点启用它。

【讨论】:

  • 这是一个不错的主意,但由于我们在这个系统上运行的网站数量目前约为 5 个,并且很快会急剧增加,我认为会有一些看起来非常狡猾的切换出代码。我认为我需要尽可能地从 appcode 中剥离所有内容,将所有 web 服务移动到他们自己的项目中,包括管理系统中的 web 服务,并将它们放入自己的项目中。然后我认为主要问题将只是处理主题和母版页。
  • @MikeWyatt 您是否为不同站点共享相同的数据库表?
【解决方案2】:

我不确定我是否正确理解您的情况,但您可以在 Subversion book 第 4 章下找到有关如何维护 SVN 存储库的线索。

看来您要么必须为 SVN 树建立良好的例程,要么必须更改代码,以便尽可能地对所有网站通用,而差异是可配置的。例如,您可以使用与站点无关的代码创建一个 main 项目,然后将更改编码为构建在它之上的项目。

至于更新站点本身,这必须通过与颠覆树中的适当点同步来完成,或者您必须执行新版本(或升级)。

【讨论】:

    【解决方案3】:

    您说您有一个 SVN 存储库,其中包含所有站点的代码库。因此,除非我有误解,否则您不能简单地将任何共享组件移动到该存储库中吗?

    您提到的页面内 Javascript 等内容应尽可能设为外部。如果 HTML 布局完全不同,则 Javascript 可能会有很大不同。

    所以站点 1 和站点 2 中的这个页面是相同的,但在站点 3 中它做了一些其他站点不需要或不需要的额外操作。我们不希望这个定制功能超载,因为我们不希望/不需要它用于其他网站

    你不能在站点 3 上扩展下载代码,这样你就可以在所有站点上都有一个共同的基础,但在站点 3 上扩展它。

    【讨论】:

      【解决方案4】:

      如果我对问题的理解正确,您在一个存储库中拥有四个大致相似的网站的代码。网站实例具有自定义功能。原始帖子中的妙语,即问题,表达了对“被困在做大量复制和粘贴”的担忧。您曾多次表示对“合并”和“手动合并”感到沮丧。

      我认为您正在使用 svn 向四个主机分发新代码。

      也许您的代码库正在接近一个点,即可以将通用材料视为一个库来获利。在此视图中,四个网站中的每一个都被认为是从库构建的应用程序。如果是这样,那么在 subversion 中为这四个应用程序中的每一个都提供自己的 repo 可能是有意义的。开发工作将把通用特性与自定义特性分开,也许使“库”代码上的 API 定义得更清晰一些。然后每个主机检查库代码和自己的应用程序。

      这和你想的很接近吗?

      【讨论】:

      • 这就是我们现在所拥有的,但它包含在一个单独的 repo 中。所有网站都引用回 CORE(4 个项目组),其中包括业务、实体、数据等(我使用了 codesmith nettiers 模板)在以前的类似项目中,我设置了 Cruisecontrol.net 来构建 CORE 并分发编译好的dll 的,这不是当前关注的领域。正如您所指出的,我需要将网站分解为常用功能和自定义功能,但我该怎么做呢?像这样打破前端是我从未做过的事情
      • 您如何将网站分解为常用功能和自定义功能?这是一个很难在摘要中简明扼要地回答的问题。用具体的例子讨论可能更容易。你为什么不发布几个有代表性的片段?为了有用,片段应该在两个网站上显示相应的功能,展示通用代码和自定义代码的混合。
      • 我猜“snips”是指网站目录的布局方式?
      • 对不起。我的意思是代码 sn-ps。但是,如果您认为网站目录的布局很重要,那可能更贴切。
      • 啊,对,我不认为代码 sn-ps 真的会为此提供任何东西。虽然目录结构可能。我将它模拟并添加到原始帖子中
      【解决方案5】:

      和其他人一样,我对您的问题有些困惑,但我确实认为我对这个问题有一个大致的了解。在这种情况下,您需要尝试做的是将自定义抽象到每个客户端/项目的单独库中,并使原始代码库保持未自定义。基本代码应仅包含适用于所有网站的通用功能(尽管可以更改某些功能,以便您可以根据需要切换其可用性)。

      如果您做对了,您应该能够随时将原始代码库导出/发布到任何给定站点,而不会搞砸。任何自定义都应保持不变。

      【讨论】:

      • 我认为系统需要重新审视,并且可能会进一步分解,所以正如您所说,所有 javascript 都在外部文件中,这些文件都与相关组件很好地组织在一起。但是有没有办法将网站分成两个部分?所以我会有通用部件和定制部件?
      • 理论上,您可以模仿目录结构并在单独的项目中开发脚本/模板。然后,您将能够合并两个轨道以进行部署。实际上,这会使调试变得比应有的更加困难。我想知道是否有人对此有任何想法。
      • 我对此进行了更多思考,这就是我的做法,但它需要一个比 SVN 具有更好的分支支持的 CVS 系统。出于这个原因,我个人已经过渡到了我工作的 git。基本上,您将分叉原始代码并将其维护在单独的存储库中。从核心到分支的偶尔合并将使分支保持最新的常见更改,同时您可以在分支中进行任何自定义并从那里进行部署。成功的关键在于 git 等系统中内置的出色的自动合并跟踪功能,它负责 95% 的工作。
      【解决方案6】:

      【讨论】:

      • CI 是我将在接下来的几个月内使用 Cruisecontrol.net 设置的东西,但我目前没有任何服务器或机器来运行它。不过这很快就会改变:)
      【解决方案7】:

      三个想法,按效用和努力的升序排列:

      1) 强调“每个站点的标记完全不同(管理站点除外,这只是一个主题更改),但代码库是相同的。”

      您可以将多少“代码”移至共享的 DLL 项目?如果它几乎是全部,那么您可以为每组标记维护单独的项目,这些项目将使用 DLL 作为参考。

      显然,如果您有很多不在 AppCode 中的代码,那么这根本不可行。如果没有,这可能是减少精神错乱的捷径。

      2) 是否可以为共享代码维护一个存储库,并为每个站点使用单独的存储库?然后,您需要创建自己的部署脚本来处理从正确的存储库中提取源代码并将其放置在正确的位置。

      根据代码/标记的紧密耦合程度,这也可能不可行。

      3) 最后,如何将不同的代码移入数据库并让应用在部署时自行生成?

      显然这是最复杂的,但它会让你到达你想去的地方。

      【讨论】:

        【解决方案8】:

        首先我要感谢大家的意见。

        我现在已经(或多或少)解决了这个问题。

        我所做的是将所有图像移动到主题文件夹中,并在模板和控件文件夹中创建子文件夹,定制控件将存在于其中。 我已经在数据库模式中创建了一些特性,这些特性给了我帮助。

        我对系统的预先规划中有很多我没有完全实施并且已经忘记的内容。

        我还为 web 服务之类的东西分离了一些代码,至少对于无论如何都可以独立生存的 web 服务。

        我们共同找到了解决方案,所以我不确定将积分奖励给谁?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-14
          • 1970-01-01
          • 2011-10-28
          • 1970-01-01
          • 2010-12-16
          • 2016-01-04
          • 1970-01-01
          • 2019-05-07
          相关资源
          最近更新 更多