webpack做为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。本系列是笔者本身的学习记录,比较基础,但愿经过问题 + 解决方式的模式,之前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法。(本篇中的参数配置及使用方式均基于webpack4.0版本)css
假设项目中的CSS文件均采用预编译语言编写,那么在打包中须要处理的基本问题包括:html
旧的解决方案:预编译语言 + 命名方法论前端
在不使用构建工具的时代,开发者使用预编译语言来实现变量定义,选择器嵌套等一些刚需,再使用函数功能来实现一些更为复杂的需求,例如编写简单的@mixin px2rem( )函数来将开发中使用的px单位转换为rem单位,达到移动端自适应的目的,或是编写一些处理兼容性的函数来处理浏览器兼容性。node
命名的方法论很是多,最为流行的当属BEM,也就是采用block__Element-Modifier这样的命名方式来进行模块划分,还有提倡碎片化样式的Aotm-CSS及面向对象的OOCSS等,都是一种命名方法论,也意味着没有硬性的检测和预防措施。webpack
新的解决方案:预编译语言 + 构建工具 + BEM + ACSS全局样式+CSSModule组件样式+ POSTCSSweb
预编译语言的使用基本不变,但现代化开发中已经再也不须要经过预约义函数来解决单位转换或是兼容性的问题。首先,构建工具能够经过自动化检测将预编译语言转换为CSS,基于现代化构建工具的CSS-Module功能,能够经过特定的语法解决CSS模块化的问题,而基于POSTCSS实现的autoprefixer插件,能够依据CanIUse网站提供的浏览器支持度数据实现代码的跨浏览器前缀自动补齐。json
新的方案涉及到不少新的概念,但这并非简单的炫技,每个概念都有优势和适用的场合,你须要在恰当的场合使用恰当的技术,最愚蠢的作法就是由于某种技术热门而盲目地要求开发人员在整个项目中使用。浏览器
以webpack4.0版本为例来演示CSS模块的处理方式,须要用到的插件及功能以下:sass
本篇不是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 Module在CSS中使用类选择器,其基本原理是将CSS代码中的样式名替换为哈希值,并创建一个json对照表,在js文件中对于属性名选择器的使用均被替换为哈希字符串,以此来解决CSS模块化的问题。
在webpack中使用CSS Modules功能很是简单,只须要在css-loader的配置参数中设置:{modules:true}便可激活模块化功能。
开启模块化功能后再进行打包,能够看到一样的main.css文件变成了以下样子:
而在打包文件中增长了以下片断:
固然CSS Modules的用法远不止如此,更多的信息能够参见上面的项目地址。
从上述配置中能够看出,使用预编译器编写的样式文件须要通过一系列loader和plugin才能获得最终的目标文件,它之因此很抽象是由于中间的处理环节对开发者来讲是黑箱操做,只看获得输入和输出,笔者结合本身理解绘制了下面的示意图,但愿可以帮助你理解css文件在整个webpack打包流程中是如何被处理的(plugins部分还没有进行研究,处理链中暂不涉及)。