談談 PostCSS

2021-02-19 前端大全

(點擊上方公眾號,可快速關注)

作者:laizimo

github.com/laizimo/zimo-article/issues/41

如有好文章投稿,請點擊 → 這裡了解詳情

前言

現在的前端,javascript的發展有目共睹,框架林立。同時,html也是齊頭並進,推出了HTML5標準,並且得到了普及。這樣的發展卻唯獨少了一個角色?

CSS,就是這個看似不起眼的傢伙,卻在開發中發揮著和js一樣重要的作用。

css,是一種樣式腳本,好像和程式語言有著一定的距離,我們可以將之理解為一種描述方法。這似乎導致css被輕視了。不過,css近幾年來正在經歷著一次巨變——CSS Module。我記得js的井噴期應該可以說是node帶來的,它帶來了Module的概念,使得JS可以被工程化開發項目。那麼,今天的css,也將越來越美好。如果你喜歡我的文章,歡迎評論,歡迎Star~。歡迎關注我的github博客

正文

既然作為一篇推廣PostCSS的文章,我們就應該先來了解一下這是什麼,和我們之前講的CSS Module有啥關係?此處讓我為你們娓娓道來。

我想和你們說再見

目前,在工程化開發中,使用最多的應該就是Less、Sass和Stylus。首先,還是介紹一下它們吧。它們有個統一的名字——css預處理器。何為CSS預處理器?應該就是一種可以將你根據它的規則寫出來的格式轉成css的東西(還是講的通俗一點)。它們的出現可以說是恰逢其時,解決了css的一些缺憾:

面對以上問題,css預處理器給出了非常可行的解決方案:

變量:就像其他程式語言一樣,免於多處修改。

作用域:有了變量,就必須得有作用域進行管理。就想js一樣,它會從局部作用域開始往上查找變量。

Sass:它的方式是三者中最差的,不存在全局變量的概念

Less:它的方式和js比較相似,逐級往上查找變量

Stylus:它的方式和Less比較相似,但是它和Sass一樣更傾向於指令式查找

嵌套:對於css來說,有嵌套的寫法無疑是完美的,更像是父子層級之間明確關係

有了這些方案,會使得我們可以在保證DPY、可維護性、靈活性的前提下,編寫css樣式。

回到話題中,之所以會出現向預處理器這樣子的解決方案,歸根結底還是css標準發展的滯後性導致的。同時,我們也應該考慮一下,真的只要預處理器就夠了嗎?往往在項目過大時,由於缺乏模塊的概念,全局變量的問題會持續困擾著你。每次定義選擇器時,總是要顧及到其他文件中是否也使用了同樣的命名。畢竟項目是團隊的,而不是個人的。哪是否有方式可以解決這些問題呢?

前人的方法

對於css命名衝突的問題,由來已久,可以說我們前端開發人員,天天在苦思冥想,如何去優雅的解決這些問題。css並未像js一樣出現了AMD、CMD和ES6 Module的模塊化方案。

那麼,回到問題,如何去解決呢?我們的前人也有提出過不同的方案:

Object-Oriented CSS

BEM

SMACSS

方案可以說是層出不窮,不乏有團隊內部的解決方案。但是大多數都是一個共同點——為選擇器增加前綴。

這可是一個體力活,你可能需要手動的去編寫長長的選擇器,或許你可以使用預編譯的css語言。但是,它們似乎並為解決本質的問題——為何會造成這種缺憾。我們不妨來看看,使用BEM規範寫出來的例子:

<!-- 正確的。元素都位於 'search-form' 模塊內 --><!-- 'search-form' 模塊 -->

<form class="search-form">

    <!-- 在 'search-form' 模塊內的 'input' 元素 -->

    <input class="search-form__input" />

    <!-- 在 'search-form' 模塊內的 'button' 元素 -->

    <button class="search-form__button"></button>

</form>

<!-- 不正確的。元素位於 'search-form' 模塊的上下文之外 --><!-- 'search-form' 模塊 -->

<form class=""search-block>

</form>

<!-- 在 'search-form' 模塊內的 'input' 元素 -->

<input class="search-form__input"/>

<!-- 在 'search-form' 模塊內的 'button' 元素 -->

<button class="search-form__button"></button>

每次這樣子寫,估計是個程式設計師,都得加班吧,哈哈!

一種希望

現在的網頁開發,講究的是組件化的思想,因此,急需要可行的css Module方式來完成網頁組件的開發。自從2015年開始,國外就流行了CSS-in-JS(典型的代表,react的styled-components),還有一種就是CSS Module。

本篇談及後者,需要對前者進行了解的話,自行Google即可

對於css,大家都知道,它是一門描述類語言,並不存在動態性。那麼,要如何去形成module呢。我們可以先來看一個react使用postcss的例子:

//example.css

 

.article {

    font-size: 14px;

}

.title {

    font-size: 20px;

}

之後,將這些命名打亂:

.zxcvb{

    font-size: 14px;

}

.zxcva{

    font-size: 20px;

}

將之命名對應的內容,放入到JSON文件中去:

{

    "article": "zxcvb",

    "title": "zxcva"

}

之後,在js文件中運用:

import style from 'style.json';

 

class Example extends Component{

    render() {

        return (

            div classname={style.article}>

                div classname={style.title}>/div>

            /div>

        )

    }

}

這樣子,就描繪出了一副css module的原型。當然,我們不可能每次都需要手動去寫這些東西。我們需要自動化的插件幫助我們完成這一個過程。之後,我們應該先來了解一下postCSS。

我需要認識你

PostCSS是什麼?或許,你會認為它是預處理器、或者後處理器等等。其實,它什麼都不是。它可以理解為一種插件系統。使用它GitHub主頁上的介紹:

PostCSS is a tool for transforming CSS with JS plugins. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more.

你可以在使用預處理器的情況下使用它,也可以在原生的css中使用它。它都是支持的,並且它具備著一個龐大的生態系統,例如你可能常用的Autoprefixer,就是PostCSS的一個非常受歡迎的插件,被Google, Shopify, Twitter, Bootstrap和CodePen等公司廣泛使用。

當然,我們也可以在CodePen中使用它:

接下來,我們來看一下PostCSS的配置:

這裡我們使用webpack+postcss+postcss-loader+cssnext+postcss-import的組合。

首先,我們可以通過yarn來安裝這些包:

yarn add --dev webpack extract-text-webpack-plugin css-loader file-loader postcss postcss-loader postcss-cssnext postcss-import

 

然後,我們配置一下webpack.config.js:

const webpack = require('webpack');

const path = require('path');

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {

  context: path.resolve(__dirname, 'src'),

  entry: {

    app: './app.js';

  },

  module: {

    loaders: [

      {

        test: /\.css$/,

        use: ExtractTextPlugin.extract({

          use: [

            {

              loader: 'css-loader',

              options: { importLoaders: 1 },

            },

            'postcss-loader',

          ],

        }),

      },

    ],

  },

  output: {

    path: path.resolve(__dirname, 'dist/assets'),

  },

  plugins: [

    new ExtractTextPlugin('[name].bundle.css'),

  ],

};

然後在根目錄下配置postcss.config.js

module.exports = {

  plugins: {

    'postcss-import': {},

    'postcss-cssnext': {

      browsers: ['last 2 versions', '> 5%'],

    },

  },

};

之後,就可以在開發中使用cssnext的特性了

/* Shared */

@import "shared/colors.css";

@import "shared/typography.css";

/* Components */

@import "components/Article.css";

/* shared/colors.css */

:root {

  --color-black: rgb(0,0,0);

  --color-blue: #32c7ff;

}

 

/* shared/typography.css */

:root {

  --font-text: "FF DIN", sans-serif;

  --font-weight: 300;

  --line-height: 1.5;

}

 

/* components/Article.css */

.article {

  font-size: 14px;

  & a {

    color: var(--color-blue);

  }

  & p {

    color: var(--color-black);

    font-family: var(--font-text);

    font-weight: var(--font-weight);

    line-height: var(--line-height);

  }

  @media (width > 600px) {

    max-width: 30em;

  }

}

最後使用webpack進行編譯就可以了。

總結

PostCSS,國內還沒有太流行起來,不過相信不久的將來也會逐漸的熱門,並且國內的資源較少,不過最近新出了一本大漠老師們一起翻譯的書——《深入PostCSS Web設計》。有興趣的人也可以去看一下,學習一些前言的東西。本篇也只是大概的寫了一下PostCSS的東西,鑑於國內資源較少,所以參考了一下國外的博文教材,下面會有連結。

參考連結

覺得本文對你有幫助?請分享給更多人

關注「前端大全」,提升前端技能

相關焦點

  • PostCSS (一):認識 PostCSS
    它可以作為一款 CSS 前置處理器( preprocessor ) 使用, 就像 Sass 和 Less 等一樣,使用 postcss-simple-vars, postcss-mixins, postcss-nested, postcss-sass-extend 等插件來實現 Sass 提供的 變量, mixin,選擇器嵌套,extend 等功能。
  • 7 個 PostCSS 插件讓你輕鬆步入 PostCSS
    為了在 Gulp 中使用 PostCSS,你需要建立你的項目並安裝兩個模塊:bashnpm initnpm install --save-dev gulp gulp-postcss然後,你可以繼續添加你需要的插件,如: autoprefixer(https://github.com/postcss/autoprefixer
  • postcss開發實戰
    postcss 本身不會對 css 文件進行修改,它只將 css 文件轉化為抽象語法樹(abstract syntax tree,後簡稱 ast),然後插件對語法樹進行處理,最後由 postcss 將 ast 還原為普通 css,所以 postcss 對 css 文件的修改都是基於插件來實現的。
  • PostCSS入門指南
    /node_modules/.bin並且只需執行postcss。然後用一行命令安裝它們:npm install --save-dev postcss-import postcss-simple-vars postcss-extend postcss-nested postcss-mixins autoprefixer
  • postcss介紹與實戰
    官方文檔(https://github.com/postcss/postcss)對插件就有很多種分類,建議小夥伴們抽空看一下。同時還有一個網站可以查找插件 postcss.parts(http://postcss.parts/),可以再這裡搜到你想要的插件。
  • 讓CSS更完美:PostCSS-modules
    然後生成一個JSON文件(sources map)和原本的class關聯:/* post.css */.article {  font-size: 16px;} .title {  font-weight: 24px;}上面的post.css將會被轉換成類似下面這樣:
  • 搞定你的PostCSS配置
    postcss')                }  ]},postcss: function () {    return [     ];}使用插件快速配置一覽$ npm install postcss-cssnext --save-dev$ npm install
  • 從Sass過渡到PostCSS
    在不改變任何東西情況下可以編譯CSS樣式:npm run postcss它能正常工作。在控制臺上也沒有任何的錯誤提示,但是頁面沒有任何的樣式。第一個插件可以使用postcss-import插件來替代Sass樣式中的@import功能。通過npm安裝好這個插件之後,就可以更新我們的構建腳本:
  • 深入PostCSS Web設計
    之所以這麼做,是因為我們選擇的工具允許我們同時創建這兩個處理器,這個工具就是 PostCSS,您可以前往 https://github.com/postcss/postcss 下載它。目前,業界已經有公司將 PostCSS 應用到線上產品中,比如 Twitter、Google、Bootstrap、CodePen 以及 WordPress(限制性使用部分功能)。
  • 使用 PostCSS 插件讓你的網站支持暗黑模式
    這邊選擇 CSS 和 postcss 這樣就可以將 css 解析成 CSS AST (抽象語法樹)了。astexplorer.net目的開始寫一個 PostCSS 插件我們可以使用 postcss-plugin-boilerplate[1] 這個腳手架來創建一個 postcss-plugin ,它還配置好了 jest 單元測試。通過幾個簡單命令就可以創建一個 postcss-plugin 工程。
  • CSS TreeShking 原理揭秘: 手寫 PurgeCss
    我們可以基於 posthtml 來實現 html 的提取器,它可以做 html 的 parse、分析、轉換等,api 和 postcss 類似。css 的部分使用 postcss,通過 ast 可以分析出每一條 rule。
  • CSS NEXT---CSS預處理器簡單寫法的替代者
    說到預編譯語言,不得不提起的就是當下很流行的 postcss ,終於有一點點進入正題了~postcss 是一種對 css 編譯的工具,類似 babel 對 js 的處理,其依託強大的插件體系為 CSS 處理增加了無限可能。PostCSS 一般不單獨使用,而是與已有的構建工具進行集成。PostCSS 與主流的構建工具,如 webpack 、grunt 和 gulp 都可以進行集成。
  • Tailwind CSS初體驗
    安裝taildwindcss以及它的依賴postcss,autoprefixernpm install -D tailwindcss postcss-cli autoprefixer3. 初始化postcss.config.js和tailwind.config.js文件npx tailwind init -p這樣我們的根目錄下就生成這兩個文件。4.
  • 程序屋|令人驚豔的CSS框架TailWindCSS的安裝使用教程
    在等待安裝的過程中,可以src/assets/css文件夾中新建 tailwindcss.css內容如下如果您使用的是 postcss-import最好還是用自己新建tailwindcss.css的方式import "./assets/tailwindcss.css"在項目根目錄執行以下命令:注意:一定要加-p,才會生成兩個文件。
  • 【工程化】深入淺出 CSS Modules
    ");var modulesValues = require("postcss-modules-values");postcss-modules-scope這個包主要是實現了 CSS Modules 的樣式隔離(Scope Local)以及繼承(Extend)它的代碼比較簡單
  • 來自新時代的 CSS
    >'postcss-cssnext' 已經被 'postcss-preset-env'代替了。詳情請查看 https://moox.io/blog/deprecating-cssnext/其實魚頭的腳手架裡早就把postcss-cssnext換成了postcss-preset-env,不過一直沒刪,但是看到這句話之後,處於好奇,就去翻了翻PostCSS的官網,然後又思考了下這些年CSS的發展歷程,遂有這篇文章的出爐。
  • get與post的優劣/區別和原理
    1、"get/post" VS "web 中的get/post"一些 web 相關職位的面試,無論有沒有提 web,面試中的 get/post,一般就是指 web 中的 get/post。需要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集,所以如果談 get 與 post 的區別,要是面試官有心挖坑,就要特別注意下你們聊的是不是 web 中的 get/post。
  • CSS Modules 用法教程
    App.css編譯成下面的代碼。六、輸入變量CSS Modules 支持使用變量,不過需要安裝 PostCSS 和 postcss-modules-values。$ npm install --save postcss-loader postcss-modules-values把postcss-loader加入webpack.config.js。
  • 一文詳解 CSS-in-JS
    https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99ehttps://juejin.cn/post/6844903808049348616https://www.infoq.com/news/2020/04/facebook-cssinjs-react-conf-2019/
  • 愈發熟練的 CSS 技巧
    1vw = window.innerWidth的 1%;vh : 是 Viewport height 的簡寫 1vw = window.innerHeight 1%;使用步驟假設視覺設計稿的寬度是 750px 即 1vw = 7.5px,那麼就得根據設計圖的 px 值來轉換 vw單位,為了避免這樣的計算,當然就需要使用到 PostCSS ,以及 postcss-px-to-viewport