Skip to content

CSS 组织结构:构建可扩展的样式架构

在小型项目中,把所有 CSS 写在一个文件里似乎没什么问题。但当项目逐渐增长,这个文件变得越来越大,寻找特定的样式规则就像大海捞针一样困难。团队新成员不知道应该在哪里添加新样式,修改现有样式时又担心会破坏其他地方的布局。

这就像一个没有整理的衣柜,刚开始还能勉强使用,但随着衣物越来越多,找一件特定的衣服就变得异常困难。我们需要的是一个系统化的组织方式——把衣服按类别、季节、使用频率分类存放,这样不仅能快速找到需要的衣物,还能保持整洁有序。

CSS 的组织也是如此。良好的组织结构能让代码易于理解、维护和扩展。

为什么 CSS 组织很重要?

单文件的问题

让我们看一个典型的单文件 CSS 项目会遇到的问题:

css
/* styles.css - 一个几千行的巨大文件 */

/* 重置样式 */
* {
  margin: 0;
  padding: 0;
}
html {
  font-size: 16px;
}

/* 导航栏 */
.nav {
  background-color: white;
}
.nav ul {
  list-style: none;
}
.nav li {
  display: inline-block;
}

/* 首页轮播图 */
.carousel {
  position: relative;
}
.carousel-item {
  display: none;
}

/* ... 几百行之后 ... */

/* 页脚 */
.footer {
  background-color: #333;
}

/* ... 更多样式 ... */

/* 响应式样式 */
@media (max-width: 768px) {
  .nav {
    /* ... */
  }
  /* 响应式样式散落在文件各处 */
}

/* 等等,这个导航的样式在哪里? */
/* 要修改按钮样式,需要搜索整个文件... */

这种组织方式的问题显而易见:

  1. 难以定位:找特定样式需要在几千行中搜索
  2. 容易冲突:不小心重定义了相同的选择器
  3. 难以复用:类似的样式重复出现在不同地方
  4. 协作困难:多人同时编辑容易产生冲突
  5. 加载性能:即使只需要部分样式,也要加载整个文件

良好组织的好处

相比之下,良好组织的 CSS 项目能带来:

  • 快速定位:知道每个样式在哪个文件
  • 模块化:独立的组件互不影响
  • 易于维护:修改某个模块不会破坏其他部分
  • 团队协作:不同成员可以同时工作在不同文件上
  • 性能优化:可以按需加载需要的样式
  • 代码复用:共享的样式可以轻松复用

基础文件结构

简单项目结构

对于小到中型项目,可以采用这样的结构:

styles/
├── base/
│   ├── reset.css        # 重置浏览器默认样式
│   ├── typography.css   # 字体排版
│   └── variables.css    # CSS 变量定义
├── components/
│   ├── button.css       # 按钮组件
│   ├── card.css         # 卡片组件
│   ├── form.css         # 表单组件
│   └── navigation.css   # 导航组件
├── layout/
│   ├── header.css       # 页头布局
│   ├── footer.css       # 页脚布局
│   ├── grid.css         # 网格系统
│   └── container.css    # 容器样式
├── pages/
│   ├── home.css         # 首页特定样式
│   ├── about.css        # 关于页面样式
│   └── contact.css      # 联系页面样式
├── utilities/
│   ├── helpers.css      # 辅助工具类
│   └── animations.css   # 动画效果
└── main.css             # 主文件,导入所有样式

让我们看看每个文件夹的作用:

1. Base(基础层)

基础层定义整个网站的基础样式,包括重置、变量和排版:

css
/* base/reset.css */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  line-height: 1.6;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: #333;
  background-color: #fff;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}
css
/* base/variables.css */
:root {
  /* 颜色系统 */
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  --color-danger: #e74c3c;
  --color-warning: #f39c12;
  --color-text: #333;
  --color-text-light: #666;
  --color-bg: #fff;
  --color-bg-light: #f8f9fa;

  /* 间距系统 */
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;

  /* 字体系统 */
  --font-size-sm: 14px;
  --font-size-base: 16px;
  --font-size-lg: 18px;
  --font-size-xl: 24px;
  --font-size-2xl: 32px;

  /* 阴影系统 */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);

  /* 圆角系统 */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;
  --radius-full: 9999px;
}
css
/* base/typography.css */
h1,
h2,
h3,
h4,
h5,
h6 {
  margin-top: 0;
  margin-bottom: var(--spacing-md);
  line-height: 1.2;
  font-weight: 700;
  color: var(--color-text);
}

h1 {
  font-size: var(--font-size-2xl);
}
h2 {
  font-size: var(--font-size-xl);
}
h3 {
  font-size: var(--font-size-lg);
}
h4 {
  font-size: var(--font-size-base);
}

p {
  margin-top: 0;
  margin-bottom: var(--spacing-md);
  line-height: 1.6;
}

strong {
  font-weight: 700;
}
em {
  font-style: italic;
}

code {
  padding: 2px 4px;
  font-family: "Courier New", monospace;
  background-color: var(--color-bg-light);
  border-radius: var(--radius-sm);
  font-size: 0.9em;
}

2. Components(组件层)

组件层包含可重用的 UI 组件:

css
/* components/button.css */
.button {
  display: inline-block;
  padding: var(--spacing-sm) var(--spacing-lg);
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-base);
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background-color: var(--color-bg-light);
  color: var(--color-text);
}

.button:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.button--primary {
  background-color: var(--color-primary);
  color: white;
}

.button--secondary {
  background-color: var(--color-secondary);
  color: white;
}

.button--large {
  padding: var(--spacing-md) var(--spacing-xl);
  font-size: var(--font-size-lg);
}

.button--small {
  padding: var(--spacing-xs) var(--spacing-md);
  font-size: var(--font-size-sm);
}

.button--block {
  display: block;
  width: 100%;
}
css
/* components/card.css */
.card {
  background-color: white;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: box-shadow 0.3s;
}

.card:hover {
  box-shadow: var(--shadow-lg);
}

.card__header {
  padding: var(--spacing-lg);
  background-color: var(--color-bg-light);
  border-bottom: 1px solid #e0e0e0;
}

.card__title {
  margin: 0;
  font-size: var(--font-size-lg);
  color: var(--color-text);
}

.card__body {
  padding: var(--spacing-lg);
}

.card__footer {
  padding: var(--spacing-lg);
  background-color: var(--color-bg-light);
  border-top: 1px solid #e0e0e0;
}

3. Layout(布局层)

布局层定义页面的主要结构:

css
/* layout/container.css */
.container {
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--spacing-lg);
  padding-right: var(--spacing-lg);
}

.container--narrow {
  max-width: 800px;
}

.container--wide {
  max-width: 1400px;
}

.container--fluid {
  max-width: 100%;
}
css
/* layout/grid.css */
.grid {
  display: grid;
  gap: var(--spacing-lg);
}

.grid--2-cols {
  grid-template-columns: repeat(2, 1fr);
}

.grid--3-cols {
  grid-template-columns: repeat(3, 1fr);
}

.grid--4-cols {
  grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 768px) {
  .grid--2-cols,
  .grid--3-cols,
  .grid--4-cols {
    grid-template-columns: 1fr;
  }
}
css
/* layout/header.css */
.header {
  background-color: white;
  box-shadow: var(--shadow-sm);
  position: sticky;
  top: 0;
  z-index: 100;
}

.header__container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-md) 0;
}

.header__logo {
  font-size: var(--font-size-xl);
  font-weight: 700;
  color: var(--color-primary);
}

.header__nav {
  display: flex;
  gap: var(--spacing-lg);
}

4. Pages(页面层)

页面层包含特定页面的样式:

css
/* pages/home.css */
.hero {
  padding: var(--spacing-xl) 0;
  text-align: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
}

.hero__title {
  font-size: var(--font-size-2xl);
  margin-bottom: var(--spacing-md);
}

.hero__subtitle {
  font-size: var(--font-size-lg);
  margin-bottom: var(--spacing-xl);
  opacity: 0.9;
}

.features {
  padding: var(--spacing-xl) 0;
}

.features__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--spacing-xl);
}

.feature {
  text-align: center;
}

.feature__icon {
  font-size: 48px;
  margin-bottom: var(--spacing-md);
  color: var(--color-primary);
}

5. Utilities(工具层)

工具层提供通用的辅助类:

css
/* utilities/helpers.css */

/* 显示控制 */
.hide {
  display: none !important;
}
.show {
  display: block !important;
}
.invisible {
  visibility: hidden;
}

/* 文本对齐 */
.text-left {
  text-align: left;
}
.text-center {
  text-align: center;
}
.text-right {
  text-align: right;
}

/* 间距工具 */
.mt-1 {
  margin-top: var(--spacing-sm);
}
.mt-2 {
  margin-top: var(--spacing-md);
}
.mt-3 {
  margin-top: var(--spacing-lg);
}
.mb-1 {
  margin-bottom: var(--spacing-sm);
}
.mb-2 {
  margin-bottom: var(--spacing-md);
}
.mb-3 {
  margin-bottom: var(--spacing-lg);
}

/* 颜色工具 */
.text-primary {
  color: var(--color-primary);
}
.text-secondary {
  color: var(--color-secondary);
}
.text-muted {
  color: var(--color-text-light);
}

.bg-primary {
  background-color: var(--color-primary);
}
.bg-light {
  background-color: var(--color-bg-light);
}

主文件组装

css
/* main.css - 导入所有样式 */

/* 1. 基础层 - 最先加载 */
@import "base/reset.css";
@import "base/variables.css";
@import "base/typography.css";

/* 2. 布局层 */
@import "layout/container.css";
@import "layout/grid.css";
@import "layout/header.css";
@import "layout/footer.css";

/* 3. 组件层 */
@import "components/button.css";
@import "components/card.css";
@import "components/form.css";
@import "components/navigation.css";

/* 4. 页面层 */
@import "pages/home.css";
@import "pages/about.css";

/* 5. 工具层 - 最后加载,确保优先级 */
@import "utilities/helpers.css";
@import "utilities/animations.css";

大型项目结构

对于更复杂的项目,我们需要更细致的组织:

styles/
├── 01-settings/
│   ├── _colors.scss
│   ├── _typography.scss
│   └── _breakpoints.scss
├── 02-tools/
│   ├── _mixins.scss
│   └── _functions.scss
├── 03-generic/
│   ├── _normalize.scss
│   └── _reset.scss
├── 04-elements/
│   ├── _headings.scss
│   ├── _links.scss
│   └── _forms.scss
├── 05-objects/
│   ├── _container.scss
│   ├── _grid.scss
│   └── _media.scss
├── 06-components/
│   ├── _button.scss
│   ├── _card.scss
│   ├── _navigation.scss
│   └── _modal.scss
├── 07-utilities/
│   ├── _spacing.scss
│   ├── _text.scss
│   └── _display.scss
└── main.scss

这种结构遵循 ITCSS(Inverted Triangle CSS)的思想,按照样式的特异性从低到高组织。

ITCSS 层级解释

1. Settings(设置层)

全局配置和变量:

scss
/* 01-settings/_colors.scss */
$color-primary: #3498db;
$color-secondary: #2ecc71;
$color-danger: #e74c3c;

$colors: (
  "primary": $color-primary,
  "secondary": $color-secondary,
  "danger": $color-danger,
);
scss
/* 01-settings/_breakpoints.scss */
$breakpoints: (
  "sm": 576px,
  "md": 768px,
  "lg": 992px,
  "xl": 1200px,
);

2. Tools(工具层)

Mixins 和 Functions:

scss
/* 02-tools/_mixins.scss */
@mixin respond-to($breakpoint) {
  @media (min-width: map-get($breakpoints, $breakpoint)) {
    @content;
  }
}

@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}

@mixin truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
scss
/* 02-tools/_functions.scss */
@function spacing($multiplier) {
  @return $multiplier * 8px;
}

@function color($name) {
  @return map-get($colors, $name);
}

3. Generic(通用层)

重置和标准化样式:

scss
/* 03-generic/_reset.scss */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 16px;
}

body {
  margin: 0;
  font-family: system-ui, sans-serif;
}

4. Elements(元素层)

裸元素样式:

scss
/* 04-elements/_headings.scss */
h1,
h2,
h3,
h4,
h5,
h6 {
  margin-top: 0;
  margin-bottom: spacing(2);
  line-height: 1.2;
  font-weight: 700;
}

h1 {
  font-size: 2rem;
}
h2 {
  font-size: 1.5rem;
}
h3 {
  font-size: 1.25rem;
}

5. Objects(对象层)

设计模式和布局对象:

scss
/* 05-objects/_container.scss */
.o-container {
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  padding-left: spacing(2);
  padding-right: spacing(2);
}
scss
/* 05-objects/_grid.scss */
.o-grid {
  display: grid;
  gap: spacing(2);
}

.o-grid--2-cols {
  grid-template-columns: repeat(2, 1fr);
}

6. Components(组件层)

具体的 UI 组件:

scss
/* 06-components/_button.scss */
.c-button {
  display: inline-block;
  padding: spacing(1) spacing(2);
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;

  &--primary {
    background-color: color("primary");
    color: white;
  }

  &--large {
    padding: spacing(2) spacing(3);
    font-size: 1.125rem;
  }
}

7. Utilities(工具层)

单一用途的工具类:

scss
/* 07-utilities/_spacing.scss */
@each $size in (1, 2, 3, 4) {
  .u-mt-#{$size} {
    margin-top: spacing($size) !important;
  }
  .u-mb-#{$size} {
    margin-bottom: spacing($size) !important;
  }
  .u-pt-#{$size} {
    padding-top: spacing($size) !important;
  }
  .u-pb-#{$size} {
    padding-bottom: spacing($size) !important;
  }
}

模块化策略

组件独立性

每个组件应该是自包含的,不依赖外部样式:

css
/* ❌ 不好的做法:组件依赖外部 */
.button {
  /* 依赖全局的 .container */
}

.container .button {
  padding: 10px;
}

/* ✅ 好的做法:组件自包含 */
.button {
  padding: 10px 20px;
  /* 所有必要的样式都在这里 */
}

文件命名约定

保持一致的文件命名:

✅ 好的命名:
- button.css
- navigation.css
- user-profile.css

❌ 避免:
- btn.css (太简写)
- Navigation.css (大写)
- user_profile.css (下划线,不一致)

导入顺序的重要性

样式的导入顺序会影响优先级:

css
/* 正确的顺序 */
@import "base/reset.css"; /* 1. 重置 */
@import "base/variables.css"; /* 2. 变量 */
@import "layout/grid.css"; /* 3. 布局 */
@import "components/button.css"; /* 4. 组件 */
@import "utilities/helpers.css"; /* 5. 工具类(最后,最高优先级) */

/* ❌ 错误的顺序 */
@import "utilities/helpers.css"; /* 工具类被后面的样式覆盖 */
@import "components/button.css";

命名空间管理

使用前缀区分不同类型的样式:

css
/* 布局 */
.l-container {
}
.l-header {
}
.l-sidebar {
}

/* 组件 */
.c-button {
}
.c-card {
}
.c-modal {
}

/* 工具类 */
.u-hide {
}
.u-text-center {
}
.u-mt-2 {
}

/* 状态 */
.is-active {
}
.is-hidden {
}
.is-loading {
}

/* JavaScript 钩子(不应用样式) */
.js-toggle {
}
.js-submit {
}

这种前缀系统的好处:

  1. 清晰的意图:一眼就能看出类的用途
  2. 避免冲突:不同前缀的类不会冲突
  3. 便于搜索:容易找到特定类型的类
  4. 团队协作:新成员快速理解代码结构

CSS 预处理器的组织

Sass/SCSS 项目结构

styles/
├── abstracts/
│   ├── _variables.scss
│   ├── _mixins.scss
│   ├── _functions.scss
│   └── _placeholders.scss
├── base/
│   ├── _reset.scss
│   ├── _typography.scss
│   └── _utilities.scss
├── layout/
│   ├── _header.scss
│   ├── _footer.scss
│   ├── _navigation.scss
│   └── _grid.scss
├── components/
│   ├── _buttons.scss
│   ├── _cards.scss
│   ├── _forms.scss
│   └── _modals.scss
├── pages/
│   ├── _home.scss
│   ├── _about.scss
│   └── _contact.scss
├── themes/
│   ├── _default.scss
│   └── _dark.scss
└── main.scss

使用部分文件(Partials)

scss
/* _variables.scss - 以下划线开头的文件是部分文件 */
$color-primary: #3498db;
$spacing-unit: 8px;

/* main.scss - 主文件导入所有部分文件 */
@import "abstracts/variables";
@import "abstracts/mixins";
@import "base/reset";
@import "components/button";
// 注意:导入时省略下划线和扩展名

模块化 Mixins

scss
/* abstracts/_mixins.scss */
@mixin button-base {
  display: inline-block;
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

@mixin button-variant($bg-color, $text-color) {
  @include button-base;
  background-color: $bg-color;
  color: $text-color;

  &:hover {
    background-color: darken($bg-color, 10%);
  }
}

/* components/_buttons.scss */
.button--primary {
  @include button-variant($color-primary, white);
}

.button--secondary {
  @include button-variant($color-secondary, white);
}

组织的最佳实践

1. 单一职责原则

每个文件应该只负责一件事:

css
/* ✅ 好:button.css 只包含按钮样式 */
.button {
  /* ... */
}
.button--primary {
  /* ... */
}
.button--large {
  /* ... */
}

/* ❌ 不好:components.css 包含所有组件 */
.button {
  /* ... */
}
.card {
  /* ... */
}
.modal {
  /* ... */
}
/* 这个文件太大了! */

2. 按功能而非页面组织

✅ 好的组织:
components/
├── button.css
├── card.css
└── navigation.css

❌ 避免:
pages/
├── home-buttons.css
├── home-cards.css
├── about-buttons.css
└── about-cards.css

3. 保持文件大小合理

✅ 理想的文件大小:
- 每个文件 50-200 行
- 超过 300 行考虑拆分

❌ 避免:
- 单个文件超过 500 行
- 文件太小(少于 20 行)也不好

4. 使用注释分隔

css
/* ==========================================================================
   Button Component
   ========================================================================== */

/**
 * 基础按钮样式
 * 用于所有按钮变体的基础
 */
.button {
  /* ... */
}

/* Button Variants
   ========================================================================== */

.button--primary {
  /* ... */
}

/* Button Sizes
   ========================================================================== */

.button--large {
  /* ... */
}

5. 建立索引文件

css
/* components/_index.css */
/**
 * Components Index
 * 
 * 这个文件导入所有组件
 * 按字母顺序排列便于查找
 */

@import "button";
@import "card";
@import "form";
@import "modal";
@import "navigation";
@import "table";

实际项目示例

让我们看一个完整的电商网站的 CSS 组织:

ecommerce-website/
├── src/
│   └── styles/
│       ├── settings/
│       │   ├── _colors.scss
│       │   ├── _typography.scss
│       │   ├── _spacing.scss
│       │   └── _breakpoints.scss
│       ├── tools/
│       │   ├── _mixins.scss
│       │   ├── _functions.scss
│       │   └── _placeholders.scss
│       ├── generic/
│       │   ├── _normalize.scss
│       │   └── _reset.scss
│       ├── elements/
│       │   ├── _page.scss
│       │   ├── _headings.scss
│       │   ├── _links.scss
│       │   ├── _lists.scss
│       │   └── _images.scss
│       ├── objects/
│       │   ├── _container.scss
│       │   ├── _grid.scss
│       │   ├── _media.scss
│       │   └── _stack.scss
│       ├── components/
│       │   ├── _header.scss
│       │   ├── _footer.scss
│       │   ├── _navigation.scss
│       │   ├── _button.scss
│       │   ├── _card.scss
│       │   ├── _product-card.scss
│       │   ├── _cart-item.scss
│       │   ├── _checkout-form.scss
│       │   ├── _search-bar.scss
│       │   ├── _filter.scss
│       │   ├── _breadcrumb.scss
│       │   └── _pagination.scss
│       ├── pages/
│       │   ├── _home.scss
│       │   ├── _product-list.scss
│       │   ├── _product-detail.scss
│       │   ├── _cart.scss
│       │   └── _checkout.scss
│       ├── utilities/
│       │   ├── _spacing.scss
│       │   ├── _text.scss
│       │   ├── _display.scss
│       │   └── _colors.scss
│       └── main.scss
└── package.json

常见问题与解决方案

问题 1:文件太多,不知道样式在哪里

解决方案:建立命名约定和文档

项目根目录/
├── STYLE_GUIDE.md    # 样式指南文档
├── styles/
│   └── README.md     # 样式结构说明

在 README 中说明:

markdown
# Styles Structure

## 目录说明

- `settings/` - 全局变量和配置
- `components/` - UI 组件样式
- `layout/` - 页面布局样式

## 添加新样式

1. 组件样式放在 `components/` 目录
2. 文件名使用小写和连字符
3. 使用 BEM 命名约定

问题 2:@import 导致多次 HTTP 请求

解决方案:使用构建工具

javascript
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
};

构建工具会将所有 @import 合并成单个文件。

问题 3:样式覆盖问题

解决方案:严格控制导入顺序

scss
/* main.scss - 严格按照特异性从低到高 */

// 1. Settings - 最低特异性
@import "settings/variables";

// 2. Generic
@import "generic/reset";

// 3. Elements
@import "elements/headings";

// 4. Objects
@import "objects/container";

// 5. Components
@import "components/button";

// 6. Utilities - 最高特异性,应该能覆盖其他样式
@import "utilities/spacing";

问题 4:团队成员不遵守组织规则

解决方案:使用 Linters 和自动化工具

json
// .stylelintrc.json
{
  "rules": {
    "selector-class-pattern": "^[a-z]([a-z0-9-]+)?(__([a-z0-9]+-?)+)?(--([a-z0-9]+-?)+){0,2}$",
    "max-nesting-depth": 3,
    "selector-max-compound-selectors": 3
  }
}

配合 Git Hooks 在提交前自动检查。

总结

良好的 CSS 组织结构是可维护项目的基础。

核心原则

  • 模块化:每个文件负责明确的功能
  • 分层清晰:基础 → 布局 → 组件 → 工具
  • 命名规范:统一的命名约定
  • 文档完善:让团队成员快速上手

组织方法

  • 小项目:简单的文件夹结构
  • 大项目:ITCSS 或类似的分层架构
  • 使用预处理器:充分利用部分文件和导入

最佳实践

  • 单一职责原则
  • 合理的文件大小
  • 清晰的注释
  • 严格的导入顺序
  • 使用构建工具

好的组织结构不是一成不变的,要根据项目的实际需求调整。最重要的是团队达成共识并坚持执行。