使用 webpack 处理 CSS 文件
作者:Seiya
时间:2019年07月09日
前言
基于模块化开发的角度,我们需要每个模块都拥有自己的 CSS 样式,在进入不同的模块时,引用不同的 CSS 样式。为了达到这样的效果,我们需要 webpack 来帮助我们对 CSS 文件进行处理。
准备
如果需要使用 webpack 解析 css 文件,需要用到以下插件:
css-loader
:用于加载 .css 文件,并且转换成 commonjs 对象;style-loader
:将样式通过<style>
标签插入到 head 中;
众所周知,CSS 在 HTML 中的常用引入方法有 <link>
标签和 <style>
标签两种,所以这次就是结合 webpack 特点实现以下功能:
将 css 通过 link 标签引入
将 css 放在 style 标签里
动态卸载和加载 css
页面加载 css 前的transform
接下来,我们编写需要编译的 CSS 代码:
*,
body {
margin: 0;
padding: 0;
}
html {
background: red;
}
<style>
标签里
CSS 放在 通常来说,css 代码放在 style 标签里可以减少网络请求次数,提高响应时间。需要注意的是,在老式 IE 浏览器中,对 style 标签的数量是有要求的。下面我们先编写 app.js 文件,如下所示:
import './css/base.css'
然后,我们编写 webpack 配置文件,如下所示:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
app: './src/app.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: __dirname + "/dist/",
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: {
singleton: true // 处理为单个style标签
}
},
{
loader: 'css-loader',
options: {
minimize: true // css代码压缩
}
}
]
}
]
}
}
<link>
标签引入
CSS 通过 link 标签通过引用 css 文件,所以需要借助 file-loader 来将 css 处理为文件。
这里 app.js 文件和上面的一样,保持不变,然后,我们来修改部分 webpack 配置,如下所示:
...
module: {
rules: [
{
test: /\.css$/, // 针对CSS结尾的文件设置LOADER
use: [
{
loader: "style-loader/url"
},
{
loader: "file-loader"
}
]
}
]
}
动态卸载和加载 CSS
style-loader 为 css 对象提供了 use 和 unuse 两种方法,借助这两种方法,可以方便快捷地加载和卸载 css 样式。
首先,我们来修改 webpack 配置,如下所示:
...
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader/useable" // 注意此处的style-loader后面的 useable
},
{
loader: "css-loader"
}
]
}
]
}
然后,我们来修改 app.js 文件,如下所示:
import base from "./css/base.css";
var flag = false;
setInterval(function() {
/* unuse 和 use 是 cssObj上的方法 */
if (flag) {
base.unuse();
} else {
base.use();
}
flag = !flag;
}, 500);
页面加载 css 前的 transform
对于 css 的 transform,简单来说:在加载 css 样式前,可以更改 css。这样,方便开发者根据业务需要,对 css 进行相关处理。
首先,我们来修改 webpack 配置,如下所示:
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: {
transform: "./css.transform.js" // transform 文件
}
},
{
loader: "css-loader"
}
]
}
]
}
下面,我们编写css.transform.js,这个文件导出一个函数,传入的参数就是 css 字符串本身。
module.exports = function(css) {
console.log(css); // 查看css
return window.innerWidth < 1000 ? css.replace("red", "green") : css; // 如果屏幕宽度 < 1000, 替换背景颜色
};
注意:
transform 是在 css 引入前根据需要修改,所以之后是不会改变的。
自动补全 CSS3 前缀
自动补全除了 PostCSS 插件外,还需要使用 autoprefixer 插件配合,具体配置如下所示:
module.exports = {
...
module: {
rules: [
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: () => {
require('autoprefixer')({
/*
* last 2 version: 表示兼容到浏览器最近的两个版本
* > 1% : 表示浏览器版本使用人数的比例
* iOS 7 : 表示兼容 iOS7 以上的版本
*/
browsers: ["last 2 version", ">1%", "iOS 7"]
})
}
}
}
]
]
}
}
注意:
autoprefixer 这个插件是根据 Can I Use 的规则进行补全的 (Can I Use)
移动端适配:px 自动转化成 rem
以前,我们使用媒体查询来实现响应式布局,这样做的缺陷就是需要写多套适配样式代码。我们现在可以使用 CSS3 最新的 rem 规范进行适配,相对于 px 规范所表示的绝对单位,rem 规范表示的是相对单位。为了实现转化,我们需要以下插件:
px2rem-loader
:根据一个样式表,生成 rem 版本和 @1x,@2x 和 @3x 样式表;lib-flexible
:动态计算根元素 font-size 的 rem 单位;
具体配置如下:
module.exports = {
...
module: {
rules: [
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
{
loader: 'postcss-loader',
options: {
plugins: () => {
require('autoprefixer')({
browsers: ["last 2 version", ">1%", "iOS 7"]
})
}
}
},
{
loader: 'px2rem-loader',
options: {
/* 1 rem = 75 px,适合 750 的视觉稿 */
remUnit: 75,
/* px 转化成 rem 时,小数点后面的位数 */
remPrecision: 8
}
}
]
]
}
}
然后通过内联的方式引入 lib-flexible,具体配置如下:
<script>${require('raw-loader!babel-loader!../node_modules/lib-flexible/flexible.js')}</script>
```