美文网首页
webpack核心,Loader打包样式资源

webpack核心,Loader打包样式资源

作者: 喜剧之王爱创作 | 来源:发表于2020-08-05 23:09 被阅读0次
    2.jpg

    写在前面

    之前的文章给大家介绍了Loader,并带大家使用了file-loaderurl-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-loadercss-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部分。为了证实这一点,大家可以检查元素,看一下

    head.PNG

    所以,我们在处理样式文件的时候一定要配合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-loadersass-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针对于样式文件的打包,看过本节文章,相信你对这一块的知识有了一定的了解也。接下来,我们将深入更深的内容,关注我,不迷路...

    相关文章

      网友评论

          本文标题:webpack核心,Loader打包样式资源

          本文链接:https://www.haomeiwen.com/subject/vwegrktx.html