Appearance
webpack 处理 css 资源
我们可以将css文件也看成是一个模块,我们是通过import来加载这个模块的,在加载这个模块时,webpack其实并不知道如何对其进行加载,我们必须制定对应的 loader 来完成这个功能。
css-loader
css-loader 就是用来解析 css 文件的,该 loader 会将 css 等价翻译为 module.exports = "${css}"
的js代码
案例:编写 component.js,在页面上添加有颜色的文字
js
import "./assets/css/index.css";
function component() {
const element = document.createElement("div");
element.innerHTML = ["Hello", "Webpack"].join(" ");
element.classList.add("content");
return element;
}
document.body.appendChild(component());
css
.content {
color: red;
font-size: 20px;
}
将 component.js 写入到配置的入口中
js
entry: {
main: './src/index.js',
component: './src/component.js'
},
打包会发现,webpack 解析模块失败了
我们需要引入 css-loader 对 css 模块进行解析
bash
npm i css-loader -D
添加配置
js
module: {
rules: [{
test: /\.css$/i,
use: ['css-loader']
}]
}
重新打包即可完成打包。编译完成后的css 会是一段 js字符串
js
var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.content {
color: red;
font-size: 20px;
}
`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
得到js代码后,还是预览不到效果,需要将代码注入到他们的 style
标签中,便会使样式生效,这就需要使用 style-loader 来实现
style-loader
style-loader 大多都用于开发环境
安装
bash
npm install style-loader -D
在配置的时候需要注意的是,loader 是有顺序的,是从右到左(换行的话可以说是从上到下),相当于链式调用 style-loader(css-loader(css))
js
module: {
rules: [{
test: /\.css$/i,
// 先解析css,再插入到页面
use: ['style-loader', 'css-loader']
}]
}
这种将 JS、CSS 代码合并进同一个产物文件的方式有几个问题:
- JS、CSS 资源无法并行加载,从而降低页面性能;
- 资源缓存粒度变大,JS、CSS 任意一种变更都会致使缓存失效。
所以 style-loader 在生产环境中不使用,使用 mini-css-extract-plugin
插件代替 style-loader
,将样式代码抽离成单独的css 文件。
mini-css-extract-plugin
用于抽离 css
安装
bash
npm i mini-css-extract-plugin -D
配置:在开发环境使用 style-loader,在生产环境使用 mini-css-extract-plugin 插件
js
const { resolve } = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = () => ({
mode: 'none',
entry: {
main: './src/index.js',
component: './src/component.js'
},
output: {
filename: '[name].js',
path: resolve(__dirname, './dist')
},
module: {
rules: [{
test: /\.css$/i,
use: [
// 根据运行环境判断使用那个 loader
(process.env.NODE_ENV === 'development' ?
'style-loader' :
MiniCssExtractPlugin.loader),
'css-loader'
]
}]
},
plugins: [
new MiniCssExtractPlugin(),
new HtmlWebpackPlugin()
]
})
打包后的css就是抽离出来了的
需要注意的是:
mini-css-extract-plugin
库同时提供 Loader、Plugin 组件,需要同时使用mini-css-extract-plugin
不能与style-loader
混用,否则报错mini-css-extract-plugin
需要与html-webpack-plugin
同时使用,才能将产物路径以link
标签方式插入到 html 中
预处理器 less、sass、stylus
在项目开发的时候,经常会使用到一些预处理器,可以借助相应的 loader 将它们先转成 css
以 less 为例:
less
@color: blue;
@fontSize: 24px;
.content {
color: @color;
font-size: @fontSize;
}
安装 less 和 less-loader
bash
npm i less less-loader -D
配置
js
module.exports = {
module: {
rules: [{
test: /\.less$/i,
use: [
// 根据运行环境判断使用那个 loader
(process.env.NODE_ENV === 'development' ?
'style-loader' :
MiniCssExtractPlugin.loader),
'css-loader',
'less-loader'
]
}]
},
}
其他预处理器
sass
bash
npm i -D sass sass-loader
js
module.exports = {
module: {
rules: [{
test: /\.s(ac)ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}]
}
}
stylus
bash
npm i -D stylus stylus-loader
js
module.exports = {
module: {
rules: [{
test: /\.styl$/i,
use: [
'style-loader',
'css-loader',
'stylus-loader'
]
}]
}
}
PostCSS
PostCSS 并没有定义一门新的语言,只是实现了一套将 CSS 源码解析为 AST 结构,并传入 PostCSS 插件做处理的流程框架,具体功能都是由插件实现。这个工具可以帮助我们进行一些CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置。
预处理器之于 CSS,就像 TypeScript 与 JavaScript 的关系;而 PostCSS 之于 CSS,则更像 Babel 与 JavaScript。
自动添加浏览器前缀案例:
bash
npm i postcss postcss-loader autoprefixer -D
通过 webpack.config.js
来配置
js
module: {
rules: [{
test: /\.css$/i,
use: [
// 根据运行环境判断使用那个 loader
(process.env.NODE_ENV === 'development' ?
'style-loader' :
MiniCssExtractPlugin.loader),
'css-loader',
{
loader: "postcss-loader",
options: {
postcssOptions: {
// 添加 autoprefixer 插件
plugins: [require("autoprefixer")],
},
},
}
]
}]
}
也可以抽离出来,通过 postcss.config.js
配置文件来进行配置
js
module.exports = {
plugins: [
require('autoprefixer')
]
}
也可以通过 postcss.json 配置文件来进行配置
json
{
"plugins":["autoprefixer"]
}
拿 user-select: none;
来举例
css
.content {
color: blue;
font-size: 24px;
user-select: none;
}
经过插件处理后自动加上了浏览器前缀
css
.content {
color: blue;
font-size: 24px;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
PostCSS 最大的优势在于其简单、易用、丰富的插件生态,基本上已经能够覆盖样式开发的方方面面。实践中,经常使用的插件有:
- autoprefixer:基于 Can I Use 网站上的数据,自动添加浏览器前缀
- postcss-preset-env:一款将最新 CSS 语言特性转译为兼容性更佳的低版本代码的插件,比如他会将8位数的颜色格式转为RGBA格式的颜色,并且它内置了 autoprefixer 功能。
- postcss-less:兼容 Less 语法的 PostCSS 插件,类似的还有:postcss-sass、poststylus
- stylelint:一个现代 CSS 代码风格检查器,能够帮助识别样式代码中的异常或风格问题