📃 前言:demo-webpack5代码地址:
🔗 gitee:code for demo-webpack@5
一、css 工程化
随着业务量及项目体量的增加,传统的 css 样式书写会使代码变得非常臃肿不便于维护和扩展,且极易产生样式冲突,于是 css 工程化应运而生,其实际上是一套方法论,使用不同的手段解决不同的问题。
⏳ 预处理器:如 Sass、less 等编程式的 css 语言,提供了增强语法,使得代码变得简洁且结构清晰,最终能编译为普通的 css 代码,以便浏览器能够解析
🎨 后处理器:如 postcss,可以在编译后的 css 代码上执行各种操作,如添加浏览器前缀、转换现代 css 功能以兼容旧浏览器等
css module:webpack 中使用的 css-loader,开启 module 配置后,能将样式类名转换为 hash值,解决类名冲突问题
其它:如提供大量预定义 css 类的框架 tailwindcss
⏳ 【预处理器】
1、安装和使用
- 构建工具为 webpack
pnpm 或者 npm、yarn 安装均可,示例中推荐使用 pnpm
# Sass
pnpm add -D node-sass sass-loader css-loader
# less
pnpm add -D less less-loader
# 如果不将 css 单独构建成独立模块,而是直接注入页面,可以再下载 style-loader
pnpm add -D style-loader
# 若要单独构建生成独立 css 文件(具体配置:后处理器 中再提)
pnpm add -D mini-css-extract-plugin
webpack.config.js 文件配置,sass 和 less 保留其一即可,下面 css-loader 未开启 module 模式,开启可见本文【后处理器】
// ... 其它配置导入模块
module.exports = {
// ... 其它配置
module:{
rules:[
// less 配置
{
test:/\.less$/,
use:['style-loder','css-loader','less-loader']
},
// sass 配置
{
test:/\.scss$/,
use:['style-loder','css-loader','sass-loader']
}
]
}
}
- 构建工具为 vite
vite.config.js 文件配置,预处理器后缀名为配置的键名,具体配置选项见官网
import { defineConfig } from 'vite'
// 不用 jsdoc 注解也可以获取类型提示
export default defineConfig({
// ...
css: {
preprocessorOptions: {
less: {
math: 'parens-division'
},
scss: {
api: 'modern-compiler', // 或 "modern","legacy"
importers: [
// ...
]
}
}
}
})
2、语法层面
🔗 less 官网
🎨 【后处理器】
1、postcss 作用
📜 postcss 的作用是:类似于 webpack 处理思路,做样式代码分析,抽象语法树分析,将分析结果交给插件,代码转换由插件完成
🔎 识别后缀名 .css 、 .pcss 、 .postcss
2、postcss 使用
- 构建工具为 webpack( postcss 配置文件见下面)
# 核心
pnpm add -D postcss postcss-loader
# 预设插件 和 打包后将 css 抽离为独立文件的插件
pnpm add -D postcss-preset-env mini-css-extract-plugin
# css-loader 将编译生成的 css 文件转换成 js 文件
pnpm add -D css-loader
mini-css-extract-plugin 迷你-css-提取-插件
使用 css-loader 后,css 最后是编译为了 js 文件,如果要抽离成 css 文件,则需要用到插件 mini-css-extract-plugin,该插件提供了一个 loader 和 插件
🚚 loader 负责记录 CSS 内容,同时导出开启 css-module 的样式对象
🎮 plugin 负责生成文件,默认情况一个 chunk 对应一个 css 文件
🎯 style-loader 引入样式是通过 js 生成 style 标签,而 MiniCssExtractPlugin.loader 是通过 link 标签引入资源文件
webpack.config.js 文件配置
💡 注意:loader 的执行顺序是自下而上,同一层级从右到左
// css 记录并提取生成独立文件的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module:{
rules:[
{
test:/\.(p)?css&/,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,//替代 style-loader
{
loader:'css-loader',
options:{
modules:{
// 这里 css-loader 开启了 module 模式,将生成的样式类名拼接hash值,避免样式重名冲突
localIdentName:'[local]_[hash:base64]'
}
}
},
'postcss-loader'
]
},
// ... sass 或 less 预处理器的配置
],
plugins:[
new MiniCssExtractPlugin({ filename:'css/' }) // 生成 css 文件
]
}
}
- 构建工具为 vite
vite 内部使用 postcss-load-config 自动加载 postcss 的配置文件 postcss.config.cjs (package.json 中指定了 "type" : "module" 否则使用 .js 后缀),因此无需单独配置,只要确保该配置文件在根目录即可
# postcss 插件预设 postcss-preset-env
# 其中内置了很多常用插件,如 autoprefixer,自动添加浏览器厂商前缀
pnpm add -D postcss postcss-preset-env
postcss.config.cjs 文件配置
module.exports = {
map: false,
plugins: {
'postcss-preset-env': {
// 哪怕是草案阶段的语法,也需要转换
stage: 0,
// 编译后,新语法不可见,比如 color:var(--color) 编译后不可见,仅展示 color:颜色
preserve: false
}
}
};
3、调整浏览器兼容范围
方式1:在 postcss-preset-env 配置中加入配置 browsers
// postcss.config.cjs
module.exports = {
plugins: {
"postcss-preset-env": {
browsers: [
"last 2 version",// 最近两个版本
"> 1%", // 支持全球市场份额超过 1% 的浏览器
"not dead" // 排除那些不再更新和使用的浏览器(没有市场份额或过时)
]
}
}
}
【方式2 - 推荐 ✨】:使用配置文件 .browserslistrc
last 2 version
> 1%
not dead
【方式3 - 推荐 ✨】:在 package.json 配置文件中配置 browserslist
{
"browserslist": [
"last 2 version",
"> 1%",
"not dead"
]
}
🧩 【css module】
webpack 中使用 scc-loader,识别css 模块内容并转换,当开启 modules 配置后,能解决样式命名冲突问题,编译后的样式类名会变为 hash 值(可配置拼接)
若结合 style-loader 能将编译后的样式放入页面 head>style 标签中,除此之外在 js 模块中能简化导入的 css 模块信息,只保留 { 原类名1: hash 值类名1,..., 原类名n: hash 值类名n }
二、js 兼容性 - babel
babel 通过各类插件,对 js 代码进行转换,以兼容不同浏览器、浏览器不同版本对 js 语法的支持
🎉 @babel/core 含 babel 操作 js 的 api
1、webpack 结合 babel
# 安装 aip 和 loader
pnpm add -D @babel/core babel-loader
# 安装预设
pnpm add -D @babel/preset-env
# 安装 core-js ,如果需要,可以安装 regenerator-runtime (生成器 function* 的转换和 async await 的转换)
pnpm add -D core-js regenerator-runtime
webpack.config.js 文件配置
// babel-loader 要在 postcss-loader、css-loader 等之前执行,因它们生成的 js 文件无需转换
module.exports = {
module:{
rules:[
// ... postcss
// ... sass 或 less 预处理器的配置
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
}
}
2、babel 配置文件
配置文件为@6.x *.babelrc,@7.x babel.config.js( package.json 指定 type为 module )
📝 使用预设(插件集合)和 插件实现代码转换,以解决兼容问题
🖇 转换时,plugins 正序执行,再倒序执行 presets
export default {
// 预设
presets: [
["@babel/preset-env", {
// 默认为 false ,设置为 usage 后,会根据使用情况,编译结果中导入 api ,如 Promise ,避免浏览器本身不支持
"useBuiltIns": "usage",
"corejs": 3
}]
],
// 插件
plugins: []
}