前端学习文章js css html

webpack的核心概念loader之打包静态资源-样式篇

2022-04-12  本文已影响0人  5cc9c8608284

1.style-loader和css-loadder

我的页面中现在有一张猫咪得图片,如下:

cat.png
但是我觉得图片有点太大了,于是我给图片加了一个avatar的类名,并在src目录下新建了一个demo.css的样式文件,对图片的大小进行了限制:
.avatar{
    width: 150px;
    height: 150px;
}

写好之后,在src目录下的入口文件index.js中引入样式文件:

import './demo.css'

然后运行npm run bundle进行打包,这时候控制台就会报一个错误,如下所示:

error.png
翻译过来就是webpack需要一个合适的loader来处理css文件,这个时候我们就需要能够处理样式的loader:style-loader,css-loader来帮我们处理样式文件了,修改webpack配置文件如下:
rules: [{
                test: /\.(jpe?g|png|gif|svg)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        name: '[name]_[hash:6]. [ext]',
                        outputPath: 'images',
                        limit: 204800 //表示当图片的大小超过200kb时,将其打包生成图片
                    }
                }
            },
            {//新增的代码
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
        ]

修改完之后还需要安装一下这两个依赖,

npm install css-loader style-loader -D

安装完成之后,运行npm run bundle再次打包,打包完成之后,打开页面,就可以看到我们的图片确实变小了:

css.png
css-loader的作用:css-loader会帮我们分析出几个css文件之间的依赖关系,最终把这些css文件合并成一个css文件;
style-loader的作用:在得到css-loader生成的内容之后,style-loader会把这段内容挂到页面的<head>中,如下所示:
style.png
这个<style>标签就是style-loader帮我们挂载到页面上的,所以在处理css文件的时候,我们需要css-loader和style-loader结合一起使用,才可以让我们的样式起作用

2.sass-loader

假如我的css文件是.scss文件,那又该如何处理呢?

//demo.scss
.avatar{
    width: 150px;
    height: 150px;
}

在index.js中导入:

//index.js
import  './demo.scss'

我们运行npm run bundle重新打包,这个时候命令行中会报一个错:

error.png
翻译过来就是webpack需要一个合适的loader去处理.scss的文件,这个时候sass-loader就出场了,安装一下这个loader:
npm install sass-loader node-sass  -D//官网有说使用sass-loader的时候,必须安装node-sass

修改配置文件如下:在rules数组中新增这个配置对象

{
                test: /\.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },

修改完成后,我们再次打包代码,这个时候就可以看到代码可以正常打包了,回到页面,可以看到我们的样式也是生效的.

注意:loader的执行顺序是从右到左,从下到上,所以当我们去打包一个scss文件的时候,实际上首先sass-loader将scss文件翻译转换成css文件,再由css-loader处理各个文件之间的依赖关系,将css文件合并成一个css文件,再由style-loader将处理好的文件添加到页面的<head>部分的<style>中。

3.postcss-loader实现自动添加浏览器厂商前缀

demo.scss文件修改如下:

.avatar{
    width: 150px;
    height: 150px;
    transform: translate(100px,100px);
    
}

安装postcss-loader:

npm install  postcss-loader   -D

要实现自动添加浏览器厂商前缀,我们还需要一个插件:autoprefixer

npm install autoprefixer  -D

postcss配置文件:

//postcss.config
module.exports = {
    plugins: [
        require('autoprefixer')
    ],
};

再次打包代码,就可以看到transform前面被添加了浏览器前缀。

4.loader的配置项

代码修改如下:

//index.js入口文件
import './demo.scss'

//demo.scss
@import './avatar.scss';
.avatar{
    width: 150px;
    height: 150px;
    transform: translate(100px,100px);  
}

//avatar.scss
body{
    height: calc(100vh - 20px);
}

也就是在之前的基础上,我在demo.scss文件中又引入了另一个scss文件,也就是在import引入的文件中,又通过@import引入了别的scss文件,那么这个时候打包对于在index.js中引入的demo.scss文件它会依次调用postcss-loader,sass-loader,css-loader,style-loader,但是打包demo.scss这个文件的时候,它里面又通过@import引入了另一个scss,那这个时候可能会出现对于avatar.scss文件没有经过postcss-loader和sass-loader的处理,就直接用css-loader和style-loader来处理了,这样显然是不对的,我想让在demo.scss文件中通过@import导入的scss文件也通过postcss-loader,sass-loader,css-loader,style-loader这几个loader的处理,这个时候,就需要修改一下配置文件了:

{
                test: /\.scss$/,
                use: ['style-loader', {
                    loader: 'css-loader',
                    options: {//新增加的
                        importLoaders: 2
                    }
                }, 'sass-loader', 'postcss-loader']
            },

importLoaders: 2意思是通过@import导入的文件也需要postcss-loader,sass-loader这两个loader的处理,这样配置了以后就可以保证通过@import引入的scss文件也能够经过所有loader的处理,就不会有任何问题了。

5.css打包的模块化

模块化css:指某个文件内的样式只在该文件内有效,不会对其他地方的文件造成影响
首先一起看一个案例:

//src/avatar.js
    import avatar from './assets/bottom.png'
    function createAvatar() { //创建一张图片,并把图片放到页面上
        var img = new Image()
        img.className = 'avatar'
        img.src = avatar;
        document.body.appendChild(img)
    }
    export default createAvatar

下面是入口文件:

//index.js
import './demo.scss' //这样引入的样式相当于是全局样式,这样很容易造成样式的全局污染
import createAvatar from './avatar.js'//引入创建图片的js文件
import avatar from './assets/bottom.png'

createAvatar()
// 这里创建了另一张图片
var img1 = new Image()
img1.className = 'avatar'
img1.src = avatar;
document.body.appendChild(img1)

重新打包代码,你就会发现,页面中的两张图片其实都有.avatar这个类对应的样式,那如果我想让这个样式只作用于某个文件,该怎么做呢?这个时候css模块化就显得格外重要了,我们需要修改一下配置文件,给options多添加一个属性就可以了:

{
                test: /\.scss$/,
                use: ['style-loader', {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 2,
                        modules: true//新增加的
                    }
                }, 'sass-loader', 'postcss-loader']
            },

这句话的意思是开启css的模块化打包,还需要修改一下index.js文件:

import style from './demo.scss'
import createAvatar from './avatar.js' //引入创建图片的js文件
import avatar from './assets/bottom.png'

createAvatar()
// 这里创建了另一张图片
var img1 = new Image()
img1.classList.add(style.avatar)
img1.src = avatar;
document.body.appendChild(img1)

重新打包代码,完成后再回到页面,就会发现只有一个图片添加了.avatar的样式,另一张完全没有被影响,如果我们想让另一张图片也有对应的样式,只需要在对应的文件中再引入一下样式即可:

//avatar.js
    import avatar from './assets/bottom.png'
    import style from './demo.scss' //引入对应的样式

    function createAvatar() { //创建一张图片,并把图片放到页面上
        var img = new Image()
        img.classList.add(style.avatar)
        img.src = avatar;
        document.body.appendChild(img)
    }
    export default createAvatar

这样两张图片就都有.avatar的样式了,这就是css module的概念,这样做带来的好处就是一个模块里面的样式和其他模块里面的样式不会有任何的冲突,这样我们写样式就不怕会被其他地方的样式覆盖的问题.

6.webpack打包字体文件

首先我们在阿里巴巴矢量图标库下载项目需要的图标,然后将图标保存到项目中,我放在了如下目录:

font.png
样式文件iconfont.css放在了src下,入口文件中的代码如下所示:
import './iconfont.css' //导入iconfont的样式文件
var root = document.getElementById('demo');
root.innerHTML = "<i class = 'iconfont icon-icon-star '/>"//在页面添加一个i元素

修改完之后,直接打包代码,完成后回到页面就会看到小图标已经显示出来了,但是在之前的webpack中,是需要配置loader的,如下所示:

{
            test: /\.(eot|ttf|svg)$/,
            use: {
                loader: 'file-loader'
            } 
        }

但是现在已经不需要了,如果你没有将字体下载下来而是使用的线上的,做法也是一样的,都比较简单,这里就不赘述了.

上一篇下一篇

猜你喜欢

热点阅读