写在前面
之前的文章给大家介绍了Loader,并带大家使用了file-loader
和url-loader
这样的loader来处理图片,当我们查阅官网就会发现,loader的种类有很多很多,各自承担的功能也不尽相同,今天我带大家了解一下专门编译样式资源的loader,首先我们对之前的代码做如下改动
import Banner from './banner.jpg'
import './index.css'
var img = new Image()
img.src=Banner
img.classList.add('banner')
var root = document.getElementById('root')
root.append(img)
.banner {
width: 150px;
height: 150px;
}
这个时候打包我们会发现报错了,自然,我们就想到了用loader去编译这样的webpack不认识的模块。
style loader 和 css loader
通常我们要编译css样式文件,需要用到两个loader,即style-loader
和css-loader
,我们先安装,并做如下配置,打包先看一下,完事再给大家讲解
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}
我们发现,打包成功了,页面中的样式也生效了,下面我们让我将样式文件分离出去,让它再复杂一点
|--src
|--|--banner.css
@import './banner.css'
我们再来打包试一下,会发现一样的效果,那么在这些打包的过程中css-loader
为我们干了什么样的事情呢
首先css-loader
会分析出项目中的css文件之间的关系,然后将多个css模块的文件合并打包,style-loader
在检测到css-loader
为我们生成的css文件后,会把生成的css挂载到页面的head部分。为了证实这一点,大家可以检查元素,看一下
所以,我们在处理样式文件的时候一定要配合style-loader
使用!
针对高级css语法的loader
我们在通常的开发中,一般会用到注入less,sass,scss等这样的高级的样式语言,那么我们是如何编译这些语言的呢?
首先我们对我们的项目文件做如下修改,然后对应引入
// index.scss
body {
.banner {
width: 150px;
height: 150px;
}
}
当然,编译结果肯定也是报错,这个时候,又该我们修改webpack配置了。
这时候就需要我们借助其他loader把scss语法翻译成css语法了,然后就和之前的一样了。这个loader就是sass-loader
,我们可以到webpack官网查看文档介绍,安装,并做相应的配置。
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
}
这时候再编译,会发现编译成功,且head中的样式文件如下
1.PNG
这里我们要特别注意一下loader的执行是按照配置的从下到上,从右到左执行的
对于样式文件,我们有时候还会遇到一些css3的特性,我们知道,在使用css3特性的时候,一般都需要我们在属性前面加上注入-wbekit-
之类的“厂商前缀”,我们现在修改一下代理,打包一下
body {
.banner {
width: 150px;
height: 150px;
transform: translate(100px, 100px);
}
}
我们发现生成的样式文件中,并没有假如厂商前缀,其实我们也是有对应的laoder帮我们加上的,也就是postcss-loader
,我们看一下文档,做相应配置试一下效果。
use: [
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
但我们发现并没有生效,我们还需要按照postcss-loader
的配置方法,在postcss.config.js
中配置autoprefixer
插件,安装后配置如下
module.exports = {
plugins: [
require('autoprefixer')
]
}
这个尝试完,发现并不能生效,但我们的配置也是没问题的,这时候,需要我们在package.json
中配置一手(配置项目支持的浏览器版本)
"browserslist": [
"defaults",
"not ie <= 8",
"last 2 versions",
"> 1%",
"iOS >= 7",
"Android >= 4.0"
]
这样就OK了,试试吧~
扩展
上面我们介绍了过于样式打包的相关loader,接下来我们将针对样式打包再进行较深入的配置讲解
扩展css-loader配置
如果要扩展配置,那么loader配置就不是个字符串了,会变成下面这样
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
}
},
'sass-loader',
'postcss-loader'
]
其中loader项为我们使用的loader名称,options项为我们的配置项,大家看我配置了importLoaders
项,下面我简单说一下他的作用,考虑下面这种情况
@import './banner.scss';
body {
.banner {
width: 150px;
height: 150px;
transform: translate(100px, 100px);
}
}
我们在scss文件中又引入了另外的scss文件,我们在打包时,对于index.scss文件,他的loader执行顺序为从下到上一次执行一遍,但是对于其中引入的‘banner.scss’文件就会就可能会跳过postcss-loader
和sass-loader
直接进入css-loader
,这样必然会报错的,我们在css-loader
中配置importLoaders
就会保证每一个scss文件都会重新走前面两个loader。
样式打包模块化(css module)
考虑下面一种情况,假如我们不同的页面或者是使用vue/react开发的不同的组件,如果我们有相同的类名,那么当他们处于同一个样式文件作用下时就会发生覆盖,就像下面的代码一样
import Banner from './banner.jpg'
function createBanner () {
var img = new Image()
img.src=Banner
img.classList.add('banner')
var root = document.getElementById('root')
root.append(img)
}
export default createBanner
import Banner from './banner.jpg'
import './index.scss'
import createBanner from './createBanner'
createBanner()
var img = new Image()
img.src=Banner
img.classList.add('banner')
var root = document.getElementById('root')
root.append(img)
上面的代码中,我们创建了一个函数,这个函数生成一张图片,并且同样拥有'banner'的类名,我们将它引用到index.js中,这时我们打包后运行会发现,index.js中引入的index.scss样式会加在两张图片中,这是我们不想看到的,于是就有了CSS Module的概念,我们在css-loader
中加入这样的配置项目
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true,
}
},
然后再引用的时候下面这种方式引用
import style from './index.scss'
import Banner from './banner.jpg'
import style from './index.scss'
import createBanner from './createBanner'
createBanner()
var img = new Image()
img.src=Banner
img.classList.add(style.banner)
var root = document.getElementById('root')
root.append(img)
这时候再打包试试,你会发现样式之间不再相互影响了。假如有复用的需求,以同样的方式引用即可。
打包字体文件
我们改造我们的项目哈,当然也可以自己搭建一个,下面的内容和之前的没有太大关系了,我这边就直接改原来的项目成下面这样
var root = document.getElementById('root')
root.innerHTML = '<div class="test">abc</div>'
打包后运行是啥样子这里就不赘述了,大家应该能想象到,现在有这样一个需求,我们希望再页面中使用字体文件来替换我们的文本字体。
- 我们首先从iconfont官网下载几个字体图标到我们本地(下载方法自行解决)
-
然后再src目录下新建'font'文件夹,将字体文件拷如,大概文件如下
font.PNG - 我们将下载下载下来的字体文件中的‘iconfont.css’文件中的内容替换至index.scss中。并且将引用的路径写对,大概如下
@font-face {font-family: "iconfont";
src: url('./font/iconfont.eot?t=1596637328641'); /* IE9 */
src: url('./font/iconfont.eot?t=1596637328641#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('./font/iconfont.woff?t=1596637328641') format('woff'),
url('./font/iconfont.ttf?t=1596637328641') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('./font/iconfont.svg?t=1596637328641#iconfont') format('svg'); /* iOS 4.1- */
}
- 我们在自己的元素中使用字体图标类
import './index.scss'
var root = document.getElementById('root')
root.innerHTML = '<div class="iconfont iconduosesvggeshiyimeitubiao-01"></div>'
按理说,我们字体图标的样式文件,样式都配好了,打包应该会比较顺利,其实这个时候打包时报错的,因为我们的index.scss中,引用了后缀是‘.eot’‘.woff’‘.ttf’‘.svg’的文件,这时候还需要我用用file-loader
转一下,我们在配置中假如这样的配置。
{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader'
}
}
这个时候再打包,发现页面就出现了我们需要的图标。
写在最后
这篇讲的东西比较多,主要是为大家介绍了,webpack针对于样式文件的打包,看过本节文章,相信你对这一块的知识有了一定的了解也。接下来,我们将深入更深的内容,关注我,不迷路...
网友评论