webpack4.0各个击破(2)—— CSS篇
webpack
作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack
工具中相应的处理办法。(本篇中的参数配置及使用方式均基于webpack4.0版本
)
一. CSS文件基本处理需求
假设项目中的CSS文件均采用预编译语言编写,那么在打包中需要处理的基本问题包括:
- 预编译语言转换
- 样式文件挂载方式选择
- 代码优化(合并及压缩)
- 去除或保留指定格式的注释
- 资源定位路径的转换
- 响应式布局单位转换【可选】
- 模块化【可选】
- 处理浏览器兼容【可选】
二. 解决方案的升级
旧的解决方案:
预编译语言
+命名方法论
在不使用构建工具的时代,开发者使用预编译语言来实现变量定义,选择器嵌套等一些刚需,再使用函数功能来实现一些更为复杂的需求,例如编写简单的
@mixin px2rem( )
函数来将开发中使用的px单位转换为rem单位,达到移动端自适应的目的,或是编写一些处理兼容性的函数来处理浏览器兼容性。命名的方法论非常多,最为流行的当属
BEM
,也就是采用block__Element-Modifier这样的命名方式来进行模块划分,还有提倡碎片化样式的Aotm-CSS
及面向对象的OOCSS
等,都是一种命名方法论,也意味着没有硬性的检测和预防措施。新的解决方案:
预编译语言
+构建工具
+BEM + ACSS全局样式
+CSSModule组件样式
+POSTCSS
预编译语言的使用基本不变,但现代化开发中已经不再需要通过预定义函数来解决单位转换或是兼容性的问题。首先,构建工具可以通过自动化检测将预编译语言转换为
CSS
,基于现代化构建工具的CSS-Module
功能,可以通过特定的语法解决CSS模块化的问题,而基于POSTCSS
实现的autoprefixer
插件,可以依据CanIUse网站提供的浏览器支持度数据实现代码的跨浏览器前缀自动补齐。新的方案涉及到很多新的概念,但这并不是简单的炫技,每一个概念都有优点和适用的场合,你需要在恰当的场合使用恰当的技术,最愚蠢的做法就是因为某种技术热门而盲目地要求开发人员在整个项目中使用。
三. 基本使用方法
3.1 常用插件及功能简述
以webpack4.0
版本为例来演示CSS模块的处理方式,需要用到的插件及功能如下:
style-loader
——将处理结束的CSS代码存储在js中,运行时嵌入<style>
后挂载至html
页面上css-loader
——加载器,使webpack
可以识别css
模块postcss-loader
——加载器,下一篇将详细描述sass-loader
——加载器,使webpack
可以识别scss/sass
文件,默认使用node-sass
进行编译mini-css-extract-plugin
——插件,4.0版本启用的插件,替代原extract-text-webpack-plugin
插件,将处理后的CSS代码提取为独立的CSS文件optimize-css-assets-webpack-plugin
——插件,实现CSS代码压缩autoprefixer
——自动化添加跨浏览器兼容前缀
3.2 webpack的配置
本篇不是webpack
教程,在此直接给出带有注释的webpack.config.js
的配置以供参考,示例中使用SCSS
作为预编译语言,其他预处理语言配置方式基本一致:
const HtmlWebpackPlugin = require('html-webpack-plugin');//用于自动生成html入口文件的插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//将CSS代码提取为独立文件的插件
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");//CSS模块资源优化插件
module.exports = {
mode:'development',
entry:'./main.js',
output:{
filename:'main.bundle.js',
path:__dirname + '/build'
},
module: {
rules: [
{
test: /\.scss$/,
exclude: /node_modules/, //排除node_modules文件夹
use: [{
loader: MiniCssExtractPlugin.loader//建议生产环境采用此方式解耦CSS文件与js文件
},{
loader: 'css-loader',//CSS加载器
options: {importLoaders: 2}//指定css-loader处理前最多可以经过的loader个数
},{
loader: 'postcss-loader',//承载autoprefixer功能
},{
loader: 'sass-loader'//SCSS加载器,webpack默认使用node-sass进行编译
}
]
}
]
},
plugins:[
new HtmlWebpackPlugin(),//生成入口html文件
new MiniCssExtractPlugin({
filename: "[name].css"
})//为抽取出的独立的CSS文件设置配置参数
],
optimization:{
//对生成的CSS文件进行代码压缩 mode='production'时生效
minimizer:[
new OptimizeCssAssetsPlugin()
]
}
}
postcss.config.js
的配置较为简单:
module.exports = {
plugins:[
require('autoprefixer')
]
}
package.json
中增加新的参数指定打包需要支持的浏览器类别:
"browerslist": [
"last 2 versions",
"IE 8",
"UCAndroid"
]
编写一段待SCSS
代码:
//变量定义
$grey: #1e1e1d;
$yellow: #ffad15;
$offwhite: #f8f8f8;
$darkerwhite: darken($offwhite, 15);//SCSS函数
$baseFontSize:14px;
//循环
@for $i from 1 through 3 {
.item-#{$i} { width: 2em * $i; }
}
//mixin
@mixin px2rem($name, $px){
#{$name}: $px / $baseFontSize * 1rem;
}
//嵌套
.class3{
font-weight: bold;
display:flex;
&-small{
color: $offwhite;
@include px2rem('font-size',14px);
}
}
//autoprefixer
::placeholder{
width:10px;
}
可以看到转换后的结果:
提示:代码压缩等优化功能在4.0版本中默认当mode : 'production'时有效。
四. 使用CSS-Modules
项目地址:CSS Modules开源地址
CSS Module在CSS中使用类选择器,其基本原理是将CSS代码中的样式名替换为哈希值,并建立一个json
对照表,在js
文件中对于属性名选择器的使用均被替换为哈希字符串,以此来解决CSS模块化的问题。
在webpack中使用CSS Modules
功能非常简单,只需要在css-loader
的配置参数中设置:{modules:true}即可激活模块化功能。
开启模块化功能后再进行打包,可以看到同样的main.css
文件变成了如下样子:
而在打包文件中增加了如下片段:
当然CSS Modules
的用法远不止如此,更多的信息可以参见上面的项目地址。
五. 图解Css-Process-Chain
从上述配置中可以看出,使用预编译器编写的样式文件需要经过一系列loader
和plugin
才能得到最终的目标文件,它之所以很抽象是因为中间的处理环节对开发者来说是黑箱操作,只看得到输入和输出,笔者结合自己理解绘制了下面的示意图,希望能够帮助你理解css文件在整个webpack
打包流程中是如何被处理的(plugins
部分尚未进行研究,处理链中暂不涉及)。
webpack4.0各个击破(2)—— CSS篇的更多相关文章
- Webpack4.0各个击破(6)loader篇
目录 一. loader综述 二. 如何写一个loader 三. loader的编译器本质 [参考] 一. loader综述 loader是webpack的核心概念之一,它的基本工作流是将一个文件以字 ...
- webpack4.0各个击破(5)—— Module篇
webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决 ...
- webpack4.0各个击破(7)—— plugin篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- Webpack4.0各个击破(10)integration篇
一. Integration 下文摘自webpack中文网: 首先我们要消除一个常见的误解,webpack是一个模块打包工具(module bundler),它不是一个任务执行工具,任务执行器是用来自 ...
- Webpack4.0各个击破(8)tapable篇
目录 一. tapable概述 二. tapable-0.2源码解析 2.1 代码结构 2.2 事件监听方法 2.3 事件触发方法 三. tapable1.0概述 一. tapable概述 tapab ...
- Webpack4.0各个击破(7)plugin篇
目录 一. plugin概述 1.1 Plugin的作用 1.2 Compiler 1.3 Compilation 二. 如何写一个plugin 四. 实战 [参考] 一. plugin概述 1.1 ...
- Webpack4.0各个击破(5)module篇
一. 模块化乱炖 脚本合并是基于模块化规范的,javascript模块化是一个非常混乱的话题,各种[*MD]规范乱飞还要外加一堆[*.js]的规范实现.现代化前端项目多基于框架进行开发,较为流行的框架 ...
- Webpack4.0各个击破(1)html篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- webpack4.0各个击破(4)—— Javascript & splitChunk
目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 ...
随机推荐
- 3.jmeter接口测试---脚本录制
安装好jmeter后,就要进入主题了,进行接口测试,接口测试的脚本获取方式 ①手动填写 ②badboy录制后,导入jmeter使用 ③jmeter录制 不会安装的可以进入这里:https://www. ...
- 使用Ant Design的select组件时placeholder不生效/不起作用的解决办法
先来说说使用Ant Design和Element-ui的感觉吧. 公司的项目开发中用的是vue+element-ui,使用了一通下来后,觉得element-ui虽然也有一些问题或坑,但这些小问题或坑凭 ...
- Go语言基础之反射
Go语言基础之反射 本文介绍了Go语言反射的意义和基本使用. 变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息. 值信息:程序运行过程中可动态变化的. 反射介绍 反射是指 ...
- 4.24Linux(4)
2019-4-24 21:35:13 学完了Linux装python编译安装感觉有种控制电脑的感觉!感觉好爽!!!! 主要是Linux用习惯就感觉好爽!!! 越努力,越幸运!永远不要高估自己!! 等学 ...
- Markdown基础语法笔记
# 一级标题## 二级标题### 三级标题###### #号之后记得加一个空格 仅支持1-6级标题 ### 列表 - 文本1 - 文本2 - 文本3+ 列表2* 列表2 ### 有序列表1. 有序文 ...
- oracle启动服务和监听
1.故障问题:tomcat显示启动oracle数据库失败,数据库服务启动正常 操作1:重启tomcat查看错误信息 2:重启数据库服务 命令: (1) 启动Oracle服务 C:\Users\Admi ...
- 《JavaScript DOM编程艺术》学习笔记(二)
终于开始接着写我的读书笔记了. 17.DOM有insertBefore方法,但并没有提供insertAfter()方法.不过可利用已有的DOM方法和属性编写此函数: function insertAf ...
- Spring框架中<constructor-arg>与<property>理解
配置文件的根元素是beans,每个组件使用bean元素来定义,bean元素可以有许多属性,其中有两个是必须的:id和class.id表示组件的默认名称,class表示组件的类型. 依赖注入的方式: ...
- DCOS实践分享(5):Open DCOS深入分析
2016/05/18(三) 09:30 OpenDC/OS研討會暨工作坊 指導單位:經濟部.科技部 主辦單位:工業技術研究院.Linker Networks 協辦單位:Microsoft.資通訊產業聯 ...
- SDL 开发实战(四): SDL 事件处理
在前面学习SDL的例子运行时,我们发现我们的窗口只停留了几秒,但是如果设置更长时间显然也有其他的弊端. 那么有没有一种好的办法可以解决这个问题呢?例如:能不能让窗口一直显示,直到检测到用户用鼠标点击关 ...