Postcss 简明教程 及 css module

在前端开发中一直有个原则,叫做"关注点分离",意思就是各种技术只负责自己的领域,不要混合在一起,形成耦合,这种原则比较直观的体现就是不要写"行内样式"(inline style)和"行内脚本"(inline script),HTML、CSS、JavaScript各干各的事,避免混用(此处参考CSS in JS 简介)

现在前端在进行开发时,基本都被各种框架覆盖,新起一个项目,第一步都是技术选型。看看是用 React、还是用 Vue,然后再配套的去选择相关技术栈,以及相应的框架。这是技术的进度,让开发人员能比较关注业务逻辑的展开,但另一方面也可以认为这是一种枷锁。。。

由于框架的使用,使我们之前的关注点分离变的策略,现在其实都是在 js 中进行。HTML 以 虚拟DOM 的形式存在其中,css 通常是以 import 的形式载入,最终通过 webpack 之类的工具,再导出成一个独立的样式文件。

相比 HTML,框架对 CSS 都没进行什么特殊处理,也没有形成类似 JSX 的解决方案,不过这其中倒是有一个比较有意思的解决方案:css-in-js(不过在 js 中写 css,怎么都感觉有些别扭)。

另外 css 本身编程能力薄弱,社区也形成各种方案来提升 css 编程能力。相比其他方案,我感觉 Postcss 更为优雅,所以这里特别介绍下

目前是基于 postcss 7.0.31 版本

基本概念

  • Postcss是一个用 js 插件转换成 css 的工具
  • Postcss 不是预处理器

预处理器是指对 css 能力增强的功能,添加一些一些本身不是css的功能(比如嵌套、变量),通过处理后能转成普通的CSS,

  • Postcss 不是后处理器

通过一些规则把已有的css进行完善,比如添加浏览器前缀

  • Postcss 是作为一个平台的存在,利用 Postcss 提供的插件可以组合各种不同模块,来构建更为复杂的功能

Demo

此处没有使用vue或react的脚手架,为了演示完整功能,构建了一个基于Vue的开发环境,并演示加载样式和提取

  • 任意目录 npm init -y

使用这种方式,项目的名词一定不要和某些库的名词冲突,比如叫webpack,postcss,如果叫这个名词安装相关库时就会报ENOSELF的错误

  • 安装 相关依赖

npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin postcss postcss-loader mini-css-extract-plugin css-loader style-loader @babel/cli @babel/core @babel/preset-env vue-loader vue-template-compiler

npm i --save vue

* css-loader 是可以在页面中使用 import 引入 css 的能力
* style-loader 是把 css 代码生成 style 标签,放到 head 标签中
* mini-css-extract-plugin 提取css用的插件

其他包不在本文讨论范围,故不介绍

  • 新建两个文件夹 srcdist,以及 babel.config.jswebpack.config.js 和其他相关文件
/// babel.config.js
const presets = [["@babel/env"]];

module.exports = {
    presets
}
...
/// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/index.js',
    resolve: {
        extensions: ['.js', '.vue']
    },
    output: {
        filename: '[name].js',
        publicPath: '/'
    },
    mode: 'development',
    module: {
        rules: [
            {test: /\.js$/, use: 'babel-loader', exclude: /node_modules/},
            {test: /\.vue$/, use: 'vue-loader', exclude: /node_modules/},
            {test: /\.css/, use: ['style-loader', 'css-loader']}
        ]
    },
    devServer: {
        port: '8111'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/tpl/index.html'
        }),
        new VueLoaderPlugin()
    ]
}
...
/// 假定有个 app.vue 按如上设置
import '../style/app.css';

这时就可以通过 import 方式把样式文件导入到页面中,因为此时用的是 style-loader ,样式会写入到 下的