首頁  >  文章  >  web前端  >  css預處理語言的模組化實踐

css預處理語言的模組化實踐

巴扎黑
巴扎黑原創
2017-03-29 14:43:261251瀏覽

編寫css是前端工作中,一項普通而又頻繁的勞動,由於css並不是一門語言,所以在程式設計上顯得有些簡陋。對於小型專案來說,css的量還不至於龐大,問題沒有凸顯,而如果要開發和持續維護一個較為大型的項目,那就需要對css進行管理和規範了,否則會發生不可挽回的後果(嚇唬誰呢?

# 背景

上一節【從css談模組化】我們透過規範的約束,將css的編寫方式進行了優化和改進,形成一種可持續發展的路線。但還是遺留了一些問題:冗餘。雖然我們透過定義公共模組和私有模組,來委婉地分擔common的體積,但common的體積還是太大了,而且從設計上考慮,我們應該盡量多地提煉公共模組,以便更好地實現復用。最理想的情況是,所有的模組都寄存在一個公共的庫裡,哪裡需要用到就從庫中直接調過來。這個美好的願望不是不可實現的,借助預處理語言,我們可以輕易地完成這件事。

預處理語言是一種類css的語言,我們知道css本身不是語言,而預處理語言的誕生,就是為填補這一部分語言功能。它實現了變數、函數、混合的定義,以及檔案的引用、合併、壓縮功能,使得css也能面向對象,應付複雜龐大的業務。

# 目前流行的預處理語言主要有兩種:less和sass。作為學習,兩者都可以入門一下,而作為工作,盡量熟悉一種。我比較常用sass,所以以下內容都是以sass為基本語言做介紹,兩者在特性上有很多相似的地方,所以大家不必擔心實現上有什麼千差萬別。

sass

# 基本文法可以到官網(英文)或w3cplus sass guide(中文)查看學習,我們這裡只簡單地過一遍,講一些我們需要用到的內容,不會面面俱到。

sass有兩種後綴名文件:一種後綴名為sass,不使用大括號和分號;另一種就是我們這裡使用的scss文件,這種和我們平時寫的css文件格式差不多,使用大括號和分號。而本教學中所說的所有sass檔案都指後綴名為scss的檔案。在此也建議使用後綴名為scss的文件,以避免sass後綴名的嚴格格式要求報錯。 ——摘自w3cplus sass guide

# 1、嵌套(非常重要的特性)

#

sass的嵌套包括兩種:一種是選擇器的嵌套;另一種是屬性的嵌套。我們一般說起或用到的都是選擇器的嵌套。 ——摘自w3cplus sass guide

##

選擇器嵌套 所謂選擇器嵌套指的是在一個選擇器中嵌套另一個選擇器來實現繼承,從而增強了sass檔案的結構性和可讀性。在選擇器嵌套中,可以使用&表示父元素選擇器。 ——摘自w3cplus sass guide

// index.scss

.g-index {
  ...

  .g-hd {
    ...

    .m-nav { ... }
  }

  .g-bd {
    ...

    .m-news { ... }
  }

  .g-ft {
    ...

    .m-copy_right { ... }
  }

  .m-dialog {
    display: none;

    &.z-active {  // 留意此处&的用法
      display: block;
    }
  }
}

編譯後:

/* index.css */

.g-index { ... }
.g-index .g-hd { ... }
.g-index .g-hd .m-nav { ... }

.g-index .g-bd { ... }
.g-index .g-bd .m-news { ... }

.g-index .g-ft { ... }
.g-index .g-ft .m-copy_right { ... }

.g-index .m-dialog {
  display: none;
}

.g-index .m-dialog.z-active {  // 留意此处&的编译结果
  display: block;
}

是不是爽歪歪?再也不用一遍一遍地去複製和修改一大堆的選擇器,也不需要去整理它們之間的關係,只需要嵌套一下,所有的關係就如同直接看dom一樣簡單明了!解放雙手,解放雙眼,同時也提高效率。值得留意的是,我們書寫sass的時候,應該盡量保持sass的嵌套順序與dom一致,注意,是嵌套順序一致,而不是層次一致,因為並不是dom裡的所有元素都需要寫樣式。

我們再來提一個場景,說明sass的嵌套寫法利於維護,假設g-bd下原本有個模組m-article_box,現在我們要把m-article_box從g-bd遷移到g-hd中(當然這個需求有些不合理~),我們來看原始碼:

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-bd">
      <p class="m-article_box">
        <p class="hd">
          最新文章
        </p>
        <p class="bd">
          <p class="list">
            <p class="item">
              <img class="cover" />
              <p class="info">
                <p class="title">
                  <a href="#">文章标题</a>
                </p>
                <p class="desc">文章简介</p>
              </p>
            </p>
          </p>
        </p>
        <p class="ft">
          <p class="page">
            <a href="#" class="pg">1</a>
            <a href="#" class="pg">2</a>
            <a href="#" class="pg">3</a>
            <a href="#" class="pg">4</a>
          </p>
        </p>
      </p>
    </p>
  </p>
</body>
</html>
.g-bd { ... }
.g-bd .m-article_box { ... }
.g-bd .m-article_box .hd { ... }

.g-bd .m-article_box .bd { ... }
.g-bd .m-article_box .bd .list { ... }
.g-bd .m-article_box .bd .list .item { ... }
.g-bd .m-article_box .bd .list .item .cover { ... }
.g-bd .m-article_box .bd .list .item .info { ... }
.g-bd .m-article_box .bd .list .item .info .title { ... }
.g-bd .m-article_box .bd .list .item .info .desc { ... }

.g-bd .m-article_box .ft { ... }
.g-bd .m-article_box .ft .page { ... }
.g-bd .m-article_box .ft .page .pg { ... }

依照css的方式,我們就要把所有跟m-article_box有關的部分,從g-bd全部複製到g-hd裡去。這還是在模組的書寫符合規範的情況下,如果這個模組書寫不符合規範,沒有把全部結構都掛在m-article_box類下,那真的就是災難了~而現在使用sass的話,我們只需要把m-article_box的區塊整個從g-bd剪切到g-hd就完事了(這裡為了突出修改的工作量大,我特地把整個模組結構都寫全了——才不是為了湊字數。。。 ):

// 修改前
.g-hd { ... }

.g-bd {
  .m-article_box {
    .hd { ... }
    .bd {
      .list {
        .item {
          .cover {
            ...
          }

          .info {
            .title {
              ...
            }

            .desc {
              ...
            }
          }
        }
      }
    }

    .ft {
      .page {
        .pg { ... }
      }
    }
  }
}

// 修改后
.g-hd {
  .m-article_box {
    .hd { ... }
    .bd {
      .list {
        .item {
          .cover {
            ...
          }

          .info {
            .title {
              ...
            }

            .desc {
              ...
            }
          }
        }
      }
    }

    .ft {
      .page {
        .pg { ... }
      }
    }
  }
}

.g-bd { ... }

非常方便,而且不容易出錯。

2、變數(variable)

# 咱們直接上程式碼:

// index.scss

$fontSize: 16px;
$grey: #ccc;

.m-nav {
  font-size: $fontSize;
  color: $grey;
}

編譯結果:

/* index.css */

.m-nav {
  font-size: 16px;
  color: #ccc;
}

寫過程式碼的人都熟悉 參數 的用法吧,太簡單太直白了不想說太多,自己意會吧。

3.函數(function)

// pixels to rems

@function rem($px) {
    @return $px / 640 * 16rem;
}

太簡單了直白了不想說太多,自己意會吧。

4、混合(mixin)

混合,顾名思义,就是混合的意思。。。也就是我们可以事先定义一段代码块,在需要使用到的地方,直接引用(include),而在引用之前,这段代码都不会出现在编译文件中,也就是不会生成任何内容。

这也是非常重要的一个特性!我们知道common的体积非常大,而体积大的根本原因是它存放了许许多多的模块。我们设想一下,如果将每一个模块都打包成mixin,那common不就减肥成功了?!多年的顽疾终于看到希望,没有比这更让人惊喜的了!我们这就上车:

/* common.css */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }

改造后

// common.scss

@mixin m-nav {
  .m-nav { ... }
}

@mixin m-news {
  .m-news { ... }
}

@mixin m-copy_right {
  .m-copy_right { ... }
}


// index.scss

.g-index {
  @include m-nav;
  @include m-news;
  @include m-copy_right;
}

5、import

这个属性很眼熟?没错,事实上,css本身就有这个属性实现,我们可以在css文件中直接使用import来引入其他文件。那么css的import和sass的import有什么区别?从含义和用法上来说,没有区别,区别在于工作原理。css的import是阻塞的,而sass的import在编译后,其实是合并文件,最后只产出一个css文件,而css则没有合并,该多少个文件就还是多少个文件。

注意:

  1. 只有import一个.sass/.scss文件的时候,才可以省去后缀名,如果是直接import一个.css文件,要补全文件名;


  2. import之后的分号;不要漏写,会报错;


  3. sass如果import的是一个.css文件的话,那它的作用就跟css原生的import作用一样,只有import一个sass文件的时候,才是合并文件。

如下:

// index.scss
@import &#39;common&#39;;
@import &#39;a.css&#39;;

编译结果:

/* index.scss */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }

@import url(&#39;a.css&#39;);

css的import之所以没有被普遍使用是有原因的。我们可以大概猜到它的工作原理:a.css import b.css以后,当浏览器加载到页面中的a.css的时候,已经准备按照a.css的内容来渲染页面了,刚解析到第一行,发现a.css居然还import了一个b.css,于是它不得不先放下a.css(既阻塞a.css),去加载b.css,直到b.css加载完,并且优先解析它,然后才开始回来解析a.css——鬼知道b.css会不会又import了c.css……这直接导致了渲染工作滞后,引发性能问题。

说实话我还不如直接用两个link标签去同步加载a.css和b.css,效率会高一些。

所以css的import基本是被抛弃了的属性。

sass的import主要的好处就是把文件合并了,减少了请求。原本需要link好几个css文件的页面,现在只需要一个。

模块化

终于要开始干点正事了,首先我们来回顾一下,上一节我们以规范为基础构建的模块化项目,遗留了一些什么问题。

  1. 冗余 体积庞大的common;


  2. 使用cm-模块区别m-模块,使得后期开发过程中,m-模块向cm-模块转变过程比较繁琐;

……

好像,问题也不是特别多,我们一个一个解决。

为了方便,在这里我们把每个页面所对应的scss文件叫做 页面scss;把变量、函数、混合等(没有被引用或者执行的情况下)编译后不产生实际内容的代码叫做 定义类代码 ,那么相对应的其他内容就是 实际内容代码。

1、mixin.scss

我们知道,一方面,在common中过多地添加模块最终会导致common的体积过大,使得资源冗余,另一方面,为了方便维护,我们又希望尽量多地把模块公有化。

这是一对矛盾,仅靠css本身是无法解决的,但sass可以!如果我们使用mixin来代替直接书写模块,由于mixin并不直接生成代码,而是通过主动引用,才能生成对应内容,那么理论上,common就可以无限多地存放模块而不必占用一点空间!

(注意,这里说的是理论上,实际应用中,文件太过庞大的话,免不了还是要受到命名冲突的限制的,不过这问题不大。)

说干就干,我们把common中的模块全部打包成mixin:

/* common.css */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }

改造后

// common.scss

@mixin m-nav {
  .m-nav { ... }
}

@mixin m-news {
  .m-news { ... }
}

@mixin m-copy_right {
  .m-copy_right { ... }
}

调用方式如下:

// index.scss

@import &#39;common&#39;; // 记得先引入common

.g-index {
  @include m-nav;
  @include m-news;
  @include m-copy_right;
}

原本我们会在每个需要用到公共模块的页面中,先引用common,然后再引用页面css,而现在,我们只需要在页面scss中直接@import common;就可以了。

使用common:

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
  <link rel="stylesheet" type="text/css" href="./style/common.css">
  <link rel="stylesheet" type="text/css" href="./style/index.css">
</head>
<body>
  ...
</body>
</html>

改造后:

// index.scss
@import &#39;common&#39;;
<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
  <link rel="stylesheet" type="text/css" href="./style/index.css">
</head>
<body>
  ...
</body>
</html>

很完美,——至少目前为止是这样。

我们思考一个问题,common除了存放模块之外,还有没有其他内容?答案是肯定的,大家一定知道有个东西叫做css reset(或者normalize.css),这肯定是全局的;另外,如果是做后台管理系统的话,可能还会有bootstrap。当然,还有一些自定义的全局的样式,比如常见的.clearfix,等等。

这些东西目前我们也堆积在common当中,而且合情合理,因为它们都是全局的样式。但是对比起mixin来说,这些实际内容代码显得很少量,有种被淹没的感觉,使得整个common看上去就像只有mixin。但是这些实际内容代码的作用却又非常重要。为了使common的构成更加直观,我们把mixin全部都抽离出来,单独存放一个叫做mixin.scss的文件中,然后在common引用它,这样,mixin的管理更加的规范,而且common的结构也更加清晰了。

抽离mixin还有另外一个重要原因,后面会讲到的,我们希望mixin作为一个纯粹定义类代码文件,随处可以引用而不会生成多余的代码。

原本我们会在每个需要用到公共模块的页面中,先引用common,然后再引用页面css,而现在,我们只需要在页面scss中直接@import mixin;就可以了。

使用mixin:

// index.scss
@import &#39;common&#39;;  // 引入common,如果有需要,common里一样可以引入mixin
@import 'mixin';  // 引入mixin

.g-index {
  ...
}
<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
  <link rel="stylesheet" type="text/css" href="./style/index.css">
</head>
<body>
  ...
</body>
</html>

2、common.scss

好,抽离了mixin之后,我们现在来重新看回common,common里应该是些什么样的内容。上面的内容我们稍稍提到了一点,我们来展开一下。

2.1、css reset(normalize)

我们知道浏览器千差万别,各浏览器的默认样式也是不尽相同,最常见的比如body的默认内边距,p标签的默认内边距,以及ul/ol等等。这些不统一的默认样式经常让我们感到头疼,所以就有人提出一开始写样式就先把它们消除的想法,于是就催生了后来非常流行的reset.css。

起初的reset.css很简单,大概是这样的:

html, body, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ul, ol, li, p {
  margin: 0;
  padding: 0;
}

没错,就是把几乎所有会用到的标签都给去了内边距和外边距,简单粗暴,这样所有的标签就都统一了,而且在不同的浏览器下也是统一的。

其他的部分每个人有各自的补充,比如有人会把h1~h6的所有字号给定义一遍,以保证在不同浏览器下他们有统一的大小;有人会给a标签设置统一的字体颜色和hover效果,诸如此类等等。

很好,没毛病。我们把这些统称为css reset,然后再统一封装到一个叫做reset.css的文件中,然后每个页面都引用。

这种方式一直以来都挺实用,而且大家也都这么用,没出过什么问题。只是后来有人提出,这种方式太过粗暴(居然还心疼浏览器了)。。。而且会降低页面渲染的性能,最重要的是,这使得我们原本设计出来的表达各种含义的标签儿们,变得毫无特点了。。。

说的好有道理,如果你家里所有人名字不一样但是都长一个样,还有啥意思。

于是,就出现了normalize.css,normalize的目的同样是为了统一各个浏览器下各不相同的默认样式,不过它并不是简单粗暴地全部抹平,而是根据规范,来人为地把那些不符合规范的默认样式“扶正”,从而达到统一各个浏览器默认样式,同时保留各个标签原有特点的目的。

我们不能说reset与normalize这两种思想孰好孰坏,只能说各有各的特点和作用,它们的存在都是为了解决同样的问题。

2.2、插件

一般来说,一个ui插件都会至少包括一个css文件,像bootstrap、datepicker等等。假设我们项目中需要以bootstrap为基础框架,实现快速开发,那么这时候我们就需要在项目中全局引入bootstrap.min.css,当然,还有bootstrap.min.js。说到全局暴露,我们第一时间想到的是common,没错,我们可以在common中引入。

有人问,插件的.css文件怎么import?额,改一下扩展名为.scss就可以了,scss是兼容原生css语法的~

所以最终,我们的common大概是这样子的:

// common.scss

@import &#39;./reset&#39;;
@import &#39;./bootstrap.min&#39;;
@import &#39;./mixin&#39;;

事实上,如果我们不需要使用到 mixin.scss 中的变量和mixin的话,我们可以不引用它。

那么我们的页面scss应该是这样的:

// index.scss

@import &#39;./common&#39;;
@import &#39;./mixin&#39;;

.g-index {
  ...
}

干净,整洁。

3、mixin编写规范

每添加一个新角色,我们就要及时给它设置规范,好让它按照我们的期望工作别添乱。我们接下来来归纳一下mixin的书写规范。

場景一:專案裡有mixin.scss、a.scss(假設這是某個功能文件)、index.scss三個文件,mixin中定義了一個變數$fontSize: 16px;,a中定義了一個變數$color : #ccc;,我們在index中同時引用這兩個文件,那麼我們在index中是可以直接使用$fontSize和$color這兩個變數的-我的意思是,儘管在index中我們並沒有看到這兩個變數的宣告和定義,但它們就這麼存在了。

這是好事還是壞事呢?直覺告訴我,這可能有問題。沒錯,這是不是跟我們之前討論過的 污染 很像?只不過我們之前是引用了common之後,index什麼都還沒寫就已經被佔用了很多模組名,而現在是因為引用了其他文件,而佔用了index的很多變數名。另外,就維護的角度來看,這也是有問題的,如果我不事先告訴你,或者你不事先看過一遍mixin和a,你知道index中的$color是哪裡來的嗎?假設我們需要字體大小,你知道要去哪個文件修改嗎?另外,你怎麼保證同時引用mixin與a的時候,他們之間有沒有可能存在同名的變數?那誰覆蓋誰呢?這些問題看起來很小,但是當你專案規模大的時候,這可能是無法挽回的災難(嚇唬誰呢???)。

場景二:假設我們的項目有一個主題色,邊框、tab背景、導覽列背景,以及字體顏色等等,都是這個主題色,為了方便使用,不想總是用取色器去取值,於是我們在mixin中定義了一個全域變數$color: #ff9900,然後就可以愉快地到處使用了!

整個網站開發完了,一個月後,設計師突然過來跟你說:“老闆說,這個主題色要改改,有點土,咱們換個大紅。”,於是你一臉不情願然而內心卻竊喜地打開mixin,把$color的值改成了大紅,然後得瑟地對設計師說:“幸好我早有準備,搞定了,你看看吧。”,保存,打開頁面一看,設計師和你的臉都綠了,頁面怎麼這麼醜,有些字原本是主題色,但背景是紅色,而現在一改,整塊都變成紅的,內容都看不清了,有些邊框原本就是紅色的,但是字體是原本的主題色,然而現在一改,邊框跟字體都變成紅的了。

設計師:「不不不,我只是想把背景顏色改一下。」
你:「你不是說改主題色嗎?那就是所有的地方啊。」
設計師:「不用,改背景就好了。」
你:「不行啊。。。」
設計師:「為什麼不行,不就是改個背景顏色嗎?怎麼設定的就怎麼改回來呀。」
你:「不是你想的那麼簡單。。」

……

好吧我就是嚇唬你的,你要是特能折騰那麼這些都不叫事兒。

所以我們需要對(全域)變數進行管理,就像我們當初管理mixin那樣,不能想在哪裡定義就在哪裡定義,也不能動不動就修改一個全域變數:

  1. 全域變數只在mixin中定義,其他scss檔案定義的變數(無論是暴露到全域或局部)都只看作局部變量,不在目前檔案以外的地方使用(即便是在能引用到的情況下,也避免使用);


  2. # 需要使用全域變數的地方直接import mixin;


  3. 一般來說,定義全域變數應該要慎重,全域變數的數量應該盡量少;


  4. 盡可能不改動,如果需求變動,除非是對用途十分確定的情況,否則請新增一個全域變數來逐步替換需要修改的地方;


  5. 不要使用太過籠統的名詞來作為全域變量,例如color,建議直接是用色值的描述,例如$orange: #ff9900,這使得我們在維護上更方便擴展,如果色值需要修改,但是又不是所有的地方都需要修改,那麼我們可以新定義一個變數來擴展它,例如$red: red。

這些點說起來都有點飄忽,事實上也確實很難說明白為什麼要這麼做,畢竟都是經驗總結,所以大家不妨先熟悉使用sass一段時間之後,再來細細思考這些問題。

注意,以上講的這些都不是死規定,在某些時候,這個規範是需要根據實際項目而做調整的,就比如我們之後要講到的SPA。十全十美的專案是不存在的,也不存在能適用所有專案的開發模式,因地制宜才能更好地解決問題。而且我們目前提到的問題都不是致命的,致命的問題在上一節我們制定規範的時候已經避開了。

呼叫模組

# 問題,在哪裡調用模組?

答,頁面scss。

在页面scss中调用模块是一个好习惯,它使得我们在每个页面所用到的模块既是一致的又是互相隔离的,不像在common中直接引用模块那样,使得一个页面scss还没有内容的时候就已经被很多模块名污染了。

再提个问题,在页面scss的哪里调用模块?

例一,根类外:

// index.scss

@import &#39;./common&#39;;
@import &#39;./mixin&#39;;

@include m-nav;
@include m-news;
@include m-copy_right;

.g-index {
  ...
}

例二,根类内:

// index.scss

@import &#39;./common&#39;;
@import &#39;./mixin&#39;;

.g-index {
  @include m-nav;
  @include m-news;
  @include m-copy_right;

  ...
}

目前为止,这两种方式都是可以的,至于我为什么用“目前为止”这个词,那是因为我们后面将要讲到的SPA,如果用例一的方式是有问题的。所以我比较鼓励使用例二的方式。当然,我说了,目前为止例一也是没问题的。

性能优化

目前为止,我们的模块化工作已经算是完成了,其实已经可以收工了。不过我们还是可以稍微做一下优化。

1、缓存

我们需要考虑一个问题:缓存。

缓存是我们web开发中最常见的情况之一,很多时候我们都需要跟缓存打交道,特别是在做性能优化的时候。

一般来说,静态资源在被加载到浏览器之后,浏览器会把它本地缓存下来,以便下次请求同个资源的时候可以快速响应,不需要再去远程服务器加载。

我们就css来说,假设我们按照原来的方式,使用多个link去加载reset、bootstrap、common、index这几个文件的话,这几个文件都会被缓存下来,以使得下次再访问这个页面,这个页面的加载速度会快很多。

如果是从index页面跳转到about页面呢?你会发现也很快,因为about页面的全局css(reset、bootstrap、common)和index页面是一样的,而它们在你访问index的时候,已经加载过了,得益于缓存的作用,之后的页面打开都快。

我们现在的方式是,一个页面所用到的所有css文件都被合并成一个,也就不存在相同的文件可以利用缓存这样的优势了。

那我们有办法改进吗?有的!我们只需要把common独立出来,那么common就可以做为被缓存的公共文件了。最终我们从一个页面只引用一个文件变成了一个页面引用两个文件,即common和页面css:

// common.scss

@import &#39;./reset&#39;;
@import &#39;./bootstrap.min&#39;;
@import &#39;./mixin&#39;;
// index.scss

@import &#39;./mixin&#39;;

.g-index {
  ...
}

注意,不同于之前,我们这里的index.scss不再引入common.scss,所以我们最终是得到了两个css文件,而common.css是在所有页面中通过link标签引入的。

如此一来,我们就实现了既能够合并文件,减少请求数,又可以利用缓存,提高加载速度。

2、压缩

代码压缩是优化工作中最基本的一步,css的压缩空间是很大的,尤其是我们这种 垂直的书写方式 ,压缩起来是相当高效的。

在sass中这很简单,sass在编译的时候提供了几种模式,其中的compressed模式是最高效的压缩模式,记得在编译打包的时候选择compressed模式就行了。

总结

总的来说,预处理语言在使我们编程更加美好的同时,也使得规范更加的完善。在css本身无法实现的情况下,我们通过工具来完成了模块化开发。

我不会讲如何去安装和配置sass环境,因为这些w3cplus sass guide有详细的介绍了,建议使用nodejs的方式,不会捣鼓nodejs/npm的前端不是好前端。

最后,我们回到一开始提到的问题——为什么要模块化?现在我们可以先从css的工作来回答,从某种意义上讲,模块化提高了我们编程能力和解决问题的能力,使得构建一个庞大而可扩展可维护的项目成为可能,使得我们能够以架构的思维和眼光去搭建整个项目。

以上是css預處理語言的模組化實踐的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn