likes
comments
collection
share

杂谈:CSS 方案选择以及按需加载

作者站长头像
站长
· 阅读数 20

方案对比

方案开发体验设计系统模块化样式复用避免代码线性增长未使用代码剔除性能问题(运行时)性能问题(编译时)主流库
原生 CSS一般一般-
CSS Modules + CSS 预处理器良好一般Less/Sass
CSS in JS良好优秀styled-components
Atom CSS优秀优秀Tailwind CSS

场景推荐

场景方案优势
App 开发Atom CSS + CSS in JS1. 开发体验好; 2. 易与设计系统结合; 3. 样式代码不会线性增长
Library 开发CSS in JS1. 使用方不存在接入成本; 2. 配合 sideEffects 可进行 Tree Shaking

组件库样式方案

以 antd(v4 及之前版本)以及 arco 等国内组件库为例,其组件文件结构基本如下:

├── alert.js # 组件代码
├── index.js # 入口文件
└── style
    ├── css.js # 引入index.css 以及 alert 依赖的下游组件的 style/css.js
    ├── index.css
    ├── index.js # 引入 index.less 以及 alert 依赖的下游组件的 style/index.js
    └── index.less
  1. 提供 css 样式(css.js 文件),降低业务方接入成本(less-loader)

  2. 通过 style/index.js 或 style/css.js 引入下游组件的样式,使得样式按需加载成为可能

假设存在以下场景:使用者引入<Button />,<Button />依赖了<Icon />,则需要手动去引入调用组件的样式(<Button />)及其依赖的组件样式(<Icon />),遇到复杂组件极其麻烦,所以组件库开发者可以提供一份这样的 js 文件,使用者手动引入这个 js 文件,就能引入对应组件及其依赖组件的样式。

按需加载

因为组件自身是没有引入样式文件的,需要使用者去手动引入。假设我们想按需引入 Alert 组件,则需要编写如下代码:

import { Alert } from 'antd';

// 引入 less 文件
import 'antd/esm/alert/style/index.js';
// or 引入 css 文件
import 'antd/esm/alert/style/css.js';

由于此类组件库的 package.json 中都配置了 sideEffects 字段,esm 会默认被 webpack 摇树,所以无需将

import { Alert } from 'antd';

改为

import Alert from 'antd/esm/alert/index.js';

而组件库一般含有样式文件,所以需要声明 *.css 以及 *.less 为 sideEffects。故按需加载一般指样式按需加载,因为 js 按需加载的确是一件很简单的事情。

纯 js 库只要配置 sideEffects: false ,webpack 会将 js 代码进行摇树。如 react-use 以及 @ant-design/icons

手动引入样式过于麻烦,所以需要配合 babel-plugin-import,转换逻辑如下:

import { Alert } from 'antd';
// 会被默认转成如下代码
import Alert from 'antd/lib/alert';
import 'antd/lib/alert/style';

这便是大部分组件库按需加载的本质。

antd 在 v5 版本使用 css in js 方案,不存在 less 和 css 文件,配合 sideEffects:false 即可完成按需加载,无需配置任何插件,接入成本降到最低。

可能还遗留了一些必须的 css 文件,故配置如下:

杂谈:CSS 方案选择以及按需加载

业务代码如何使用 sideEffects 进行 tree shaking

  1. 使用 module.rules 配置具体文件夹即可,可控性较强;