作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Alexander是一位经验丰富的前端开发人员,曾开发过电子商务和企业网站以及web和移动应用程序.
最近有很多文章都是关于独角鲸的利弊,但大多数都是有偏见的. 本单线程架构指南解释了如何以及何时有效地使用这种风格的代码管理.
A mono repository 是一个建筑概念,基本上包含了其标题的所有含义. 而不是管理多个存储库, 您将所有独立的代码部分保存在一个存储库中. 记住这个词 isolated-这意味着单块架构与单块应用程序没有任何共同之处. You can keep many kinds of logical apps inside one repo; for example, a website and its iOS app.
这个概念相对较老,大约出现在十年前. 谷歌是最早采用这种方法管理代码库的公司之一. 你可能会问,如果它已经存在了十年,那为什么直到现在才成为一个热门话题? 大多数情况下,在过去的5到6年里,许多事情都发生了巨大的变化. ES6、SCSS预处理器、任务管理器、npm等.—nowadays, 来维护一个基于react的小应用, 你必须与项目捆绑者打交道, test suites, CI/CD scripts, 码头工人配置, 谁知道还有什么. 现在想象一下,不是一个小的应用程序, 您需要维护一个由许多功能区域组成的巨大平台. 如果你在考虑建筑, 您将需要做两件主要的事情:分离关注点并避免代码重复.
To make this happen, 你可能想要将大型功能隔离到一些包中,然后通过主应用程序中的单个入口点使用它们. 但是如何管理这些包呢? 每个包都必须有自己的工作流环境配置, 这意味着每次您想要创建一个新包时, 您必须配置一个新环境, 复制所有配置文件, and so on. Or, for example, 如果你必须改变你的构建系统中的一些东西, 你必须把每个回购都看一遍, do a commit, 创建拉取请求, 等待每一次构建, 这会让你慢下来吗. 在这一步,我们遇到的是独角兽.
而不是有很多仓库与他们自己的配置, 我们将只有一个真实的来源——单一的:一个测试套件运行者, 一个Docker配置文件, 和Webpack的一个配置. 而且你还有可扩展性, 分离关注点的机会, 与通用包共享代码, 还有很多其他的优点. Sounds nice, right? Well, it is. 但也有一些缺点. 让我们仔细看看在野外使用monorepo的确切利弊.
Monorepo Advantages:
Monorepo缺点:
在处理大型项目时,Git的性能很差. 这个问题开始只出现在 huge 每天有超过100万次提交和数百名开发人员同时在同一个repo上工作的应用程序. 当Git使用有向无环图(DAG)来表示项目的历史时,这变得特别麻烦. 有大量的提交, 任何遍历图的命令都可能随着历史的加深而变慢. 由于refs的数量(i),性能也会减慢.e., branches or tags, 可以通过删除你不再需要的refs来解决)和跟踪的文件数量(以及它们的重量), 即使重文件问题可以解决使用 Git LFS).
Note: 如今,Facebook试图用VCS的可扩展性来解决问题 通过修补水星 而且,可能很快,这将不是一个大问题.
管理单一资产的工具集在不断增长, and currently, 我们很容易迷失在各种各样的建筑系统中. 您可以随时了解流行的解决方案 this repo. 但是现在,让我们快速浏览一下现在JavaScript中大量使用的工具:
大多数工具使用非常相似的方法,但也有一些细微差别.
由于这是一个相当大的主题,我们将在本文的第2部分中更深入地研究Lerna工作流以及其他工具. 现在,让我们来大致了解一下里面是什么:
这个工具在处理语义版本时确实很有帮助, 建立构建工作流, 推销你的包裹, etc. Lerna背后的主要思想是你的项目有一个packages文件夹, 哪个包含所有独立的代码部分. 除了包之外,你还有一个主应用程序,例如它可以位于src文件夹中. Lerna中几乎所有的操作都遵循一个简单的规则——遍历所有的包, 然后对它们做一些动作, e.g.,增加包版本,更新所有包的依赖,构建所有包等.
对于Lerna,你有两种选择:
在使用第一种方法时, 您可以为包使用本地引用,基本上不需要真正关心符号链接来解析它们.
但是,如果使用第二种方法,则必须从远程导入包. (e.g., 从@yourcompanyname/packagename导入{东西};
),这意味着您将始终获得软件包的远程版本. 促进地方发展, 您必须在文件夹的根目录中创建符号链接,以使打包器解析本地包,而不是使用您的 node_modules/
. 这就是为什么在启动Webpack或您最喜欢的捆绑器之前,您必须启动 lerna bootstrap
,它将自动链接所有包.
Yarn最初是NPM包的依赖管理器, 哪一个最初不是为了支持单点pos而构建的. But in version 1.0, Yarn developers 发布了一个叫做 Workspaces. 在发布时,它不是那么稳定,但过了一段时间,它就可以用于生产项目了.
Workspace 基本上就是一个包,哪有自己的 package.json 并且可以有一些特定的构建规则(例如,一个单独的 tsconfig.json 如果你在你的项目中使用TypeScript.). 实际上,您可以使用bash在没有Yarn工作区的情况下进行管理,并具有完全相同的设置, 但是这个工具有助于简化安装和更新每个包的依赖项的过程.
乍一看,Yarn和它的工作区提供了以下有用的特性:
node_modules
文件夹中的所有包. 例如,如果你有 packages/package_a
and packages/package_b
—with their own package.json
-所有依赖项将只安装在根目录下. 这是Yarn和Lerna工作方式的区别之一.-focus
flag.Useful links:
Bazel是一个用于大规模应用程序的构建工具, 它可以处理多语言依赖关系,并支持许多现代语言(Java, JS, Go, C++, etc.). In most cases, 在中小型JS应用程序中使用Bazel是多余的, 但是规模很大, 由于它的性能,它可能会提供很多好处.
By its nature, Bazel看起来和Make很像, Gradle, Maven, 以及其他允许基于包含构建规则和项目依赖项描述的文件进行项目构建的工具. 调用Bazel中的相同文件 BUILD 位于Bazel项目的工作空间内. The BUILD file uses its Starlark一种人类可读的高级构建语言,看起来很像Python.
通常情况下,你不会遇到很多 BUILD 因为有很多样板可以很容易地在网上找到,并且已经配置好并准备好进行开发. 每当你想要构建你的项目时,Bazel基本上会做以下事情:
Useful links:
独角兽只是一个工具. 关于它是否有未来,有很多争论, 但事实是,在某些情况下, 这个工具完成它的工作,并以一种有效的方式处理它. 在过去的几年里, 这个工具已经进化了, 获得了更多的灵活性, 克服很多问题, 并且在配置方面去掉了一个复杂层.
还有很多问题需要解决, 比如糟糕的Git性能, but hopefully, 这将在不久的将来得到解决.
如果你想学习为你的应用构建一个强大的CI/CD管道,我建议 如何建立一个有效的初始部署管道与GitLab CI.
软件开发中的单块架构意味着一种方法,在这种方法中,您将应用程序作为一组紧密耦合的组件/功能组合成一个整体. 你不能使用应用范围之外的任何组件.
存储库是存储和检索源代码以安装/开发源代码的地方. Repos存储具有相关元数据的所有版本的数据, 哪一个允许历史修订或在同一项目的独立并行版本上工作.
松耦合代码已被证明是更可靠的,因为它允许我们引入更改而不必担心在其他地方破坏东西. 这使得开发更安全,并简化了重构.
符号链接(符号链接)是以相对或绝对路径的形式引用原始文件夹/文件的文件,而不是实际内容. 在这种情况下,它们被用来影响路径名解析到正确的位置.
现在最流行的将代码隔离到单独模块的方法是使用npm包(可以通过Yarn或npm完成)。. 它们与自己的配置文件一起打包到一个文件夹中,然后推送到远程服务器.
Alexander是一位经验丰富的前端开发人员,曾开发过电子商务和企业网站以及web和移动应用程序.
8
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.