大声对webpack4.0说声你好之loader基础篇资源打包讲解(二)

こ雲淡風輕ζ 提交于 2020-08-18 13:12:34

导读

哈哈哈,它踏着轻快的步伐来啦。 如果你还没有看过我的《 大声对webpack4.0说声你好之webpack的基本使用(一)》,建议您先大致浏览,因为我会接着上一节的代码继续记笔记。

本篇你将会对loader有个初步认识,还会对一些常用的静态资源打包,例如图片、样式、字体等,如果你想学习更多关于loader的知识点和其他的,记得关注我,我将会尽快更新。


思考到大家可能觉得阅读文章有些许枯燥,然后我决定将代码放到github-webpack上面,代码里面使用webpack的地方,我也写了详细的注释,如果有用请记得✨,有问题可以及时交流。

如果你是webpack的初学者,那么你跟着我的代码,手动的敲打一下键盘,相信你也能和我一样快速步入webpack的神圣殿堂。因为我会将所有的笔记都做得非常非常仔细,让你在运行的过程中不受任何阻拦。

loader

为了彻底的搞懂什么是loader,我们先来做一个小练习,通过它来认识我们的loader。

打包图片练练手

webpack号称可以对文件进行打包,我们第一部分完全是对js文件进行打包,那么我们能不能对图片进行打包呢?

首页先根目录下新建文件夹statics作为我的资源文件夹,

1. 准备资源
mkdir statics // 新建静态资源文件夹
// 拷贝一个shu.jpg的图片

2.图片资源引入到index.js中
//index.js
var avator = require('../statics/images/shu.jpg')

3.使用webpack打包
npx webpack
复制代码

顺利的就遇到了问题,打包出现了问题

ERROR in ./statics/images/shu.jpg 1:0
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
 @ ./src/index.js 5:13-49
复制代码

webpack是默认支持js文件的打包的,但是遇到了图片文件的打包,他并不知道怎么办,所以我们需要修改配置文件来告诉webpack在模块打包的时候应该怎么办。

// webpack.config.js
module: { // 模块打包配置
    rules: [ // 新增规则 可以有很多,数组
      {
        test: /\.jpg$/, // 检测文件是jpg结尾的
        use: { 
          loader: 'file-loader'
        }
      }
    ]
  },
复制代码

我们会使用到loader,但是我们并没有安装这个loader,所以在执行之前我们还会使用npm进行安装

npm install file-loader -D

npx webpack

Entrypoint main = main.js
[0] ./src/index.js 198 bytes {0} [built]
[1] ./src/header.js 325 bytes {0} [built]
[2] ./src/slider.js 325 bytes {0} [built]
[3] ./src/footer.js 326 bytes {0} [built]
[4] ./statics/images/shu.jpg 80 bytes {0} [built]
复制代码

这样就多了一个图片文件,我们打开就是我们自己的shu.jpg的内容。

在这里我们使用了一个loader,名称叫file-loader,那么我们又是怎么知道 file-loader是可以打包这个图片资源的呢?

文档地址

webpack中文文档

webpack-loader文档

我们只有阅读官方文档后,才能更好的选取自己所用的loader。现在我们来看看loader到底是什么?

loader是什么?

官方定义:webpack 可以使用 loader 来预处理文件。

实际上,loader就是我们打包文件的一种方式

再看打包图片

让我们再来看看这个打包图片的例子,因为我准备把代码上传至github,但是每个人可能看到的文章系列不同,所以我重新新建一个js文件。

// src目录下新建loader-img.js dist目录下新建loader-img.html

// loader-img.js 使用import...from 方式引入
import avator from '../statics/images/aa.jpeg'

var img = new Image
img.src = avator
var root = document.getElementById('root')
root.append(img)

// loader-img.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>打包图片文件</title>
</head>
<body>
  <div id="root"></div>
</body>
<script src="./main.js"></script>
</html>

// 配置webpack.config.js
module: { // 模块打包配置
    rules: [ // 新增规则 可以有很多,数组
      {
        test: /\.(jpg|jpeg)$/, // 检测文件是jpg或者jpeg结尾的
        use: { 
          loader: 'file-loader'
        }
      }
    ]
  },

// 打包loader-img.js
npx webpack src/loader-img.js

复制代码

ok,打包完成,这样我们就可以直接在我们的loader-img.html预览图片,得到了我们的效果。

使用loader打包vue文件

在vue的官网右上角,有个生态系统,我们可以看到是给我们提供了一个生态系统的,里面就有一个vue loader。 这个时候如果我们要配置自己的vue打包文件的话,就可以直接使用vue loader打包。

// 我们直接在modulues中新加入一条规则即可
module: { // 模块打包配置
    rules: [ // 新增规则 可以有很多,数组
      {
        test: /\.(jpg|jpeg)$/, // 检测文件是jpg/jpeg结尾的
        use: { 
          loader: 'file-loader'
        }
      },
      {
        test: /\.vue$/, // 检测文件是vue结尾的
        use: {
          loader: 'vue-loader'
        }
      }
    ]
  },
复制代码

前提是你需要自己先提前安装vue loader这个依赖。

通过几个详细的例子下来,相信你对webpack中的loader有了一定的了解。

使用loader打包静态资源

OPTIONS参数

资源自定义名称

像刚才我们打包的图片都是一些静态资源,但是我们还可以更深层次的来看看我们的loader对静态资源的处理,比如,我现在想上传一个图片,但是我希望他的名字不改变,这个时候应该怎么做呢?

use: { 
  loader: 'file-loader',
  options: {
    name: '[name].[ext]'
  }
},
复制代码

这个操作我们称为placeholder 占位符 [name]: 文件名 [hash]: 打包文件的hash值(如果不清楚,请看系列一有详解) [ext]: 文件后缀 [path]: 路径等等

npx webpack laoder-img.js
复制代码

就会帮助我们打包一个aa.jpeg的图片,我们还可以使用hash值去拼接name

name: '[name]_[hash].[ext]'
复制代码

这样就OK了。

打包到某个路径

如果我们想打包文件到某个文件夹,我们直接可以使用outputPath属性,如果你还要其他打包操作可以直接去官网查询。

outputPath: '/images'
复制代码
limit

其实我们还可以使用url-loader来打包,它会直接帮我们打包成base64格式。

如果我们直接打包成base64的话,我们就会少一个图片加载,这样就会节约一次http请求,但是,如果我们的文件过大,他就会转成很多的代码,js文件就会变得相对过大,所以我们就可以判断图片20k以内我们就使用url-loader打包,这个具体的实现思路又是怎么样的呢?

首先我们先安装url-loader

npm install url-loader -D
复制代码

判断大小使用limit参数

// options 参数
limit: 1024 * 20
复制代码

这样就会判断图片是否大于20kb,如果超过就会像file-loader一样将文件打包到dist的images文件夹下,不然的话就会直接将图片转成base64格式打包进我们的js文件中。

打包样式文件

打包css文件

webpack默认只支持js文件的打包,所以不用想我们先安装css-loader。

npm install css-loader style-loader -D
复制代码

然后我们新增css文件来修饰我们的img

// index.css
.avatar{
  width: 100px;
  height: 100px;
}

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>css-loader,style-loader,url-loader</title>
</head>
<body>
  <div id="root"></div>
</body>
<script src="./main.js"></script>
</html>

// css.js
import avatar from '../statics/images/aa.jpeg'
import '../statics/style/index.css'

var img = new Image
img.src = avatar
img.classList.add('avatar')
var root = document.getElementById('root')
root.append(img)
复制代码

我们就可以直接打包了,我们还可以一个css文件通过@import 'xx.css',这种方式来引入另一个css,这里我就不多做演示了。

打包scss文件等

官网提示,如果你想使用scss,那么就必须安装sass-loader、node-sass这两个包

// 安装loader
npm install sass-loader node-sass -D

// 修改配置
{
    test: /\.scss$/, // 检测文件是vue结尾的
    use: ['style-loader','css-loader','sass-loader']
},

// statics/style/index.scss
#root{
  .avatar{
    width: 100px;
    height: 100px;
  }
}

// css.js
// import '../statics/style/index.css'
import '../statics/style/index.scss'

// 打包
npx webpack src/css.js

复制代码

最后打开我们的laoder-img.html就可以直观的看到我们的样式生效了。

注意在loader中他是从下到上,从右到左的一个执行过程,所以我们在打包scss文件的时候,他会先执行sass-loader,将我们的代码转成css后再交到css-loader,最后再给我们的style-loader挂载到页面上。

ok,那我们接下来在来升级一下我们的打包流程。

我们在样式中修改一下我们的代码,我想让我的图片进行偏移,所以我们在样式中加上如下代码

transform: translate(100px,100px);
复制代码

然后我们在进行打包。图片按照我们理想的行为做出了偏移,我们一起来看看浏览器代码。

如期望,但是在css3中,我们遇到浏览器的兼容问题之后,我们会手写很多-webkit-等等诸多的前缀,如果如此写下去的话,不得不说是一件十分令人头疼的事情。

其实也有很多的loader为我们提供了这样的自动添加前缀的功能。

打包c3自动加前缀

1.安装 postcss-loader

// 下载postcss-loader autoprefixer插件
npm install postcss-loader -D
复制代码

2.在根目录下新建postcss.config.js

module.exports = {
  plugins: [ // 使用插件
    require('autoprefixer')({ overrideBrowserslist: ['last 15 versions'] })
  ]
}
复制代码

3.修改webpack.config.js

{
    test: /\.scss$/, // 检测文件是vue结尾的
    use: ['style-loader','css-loader','sass-loader','postcss-loader']
},
复制代码

ok,我们来进行一次梳理。

  • 我们在打包scss文件的时候,首先会使用postcss-loader
  • postcss-loader会去招到postcss的配置项
  • 在配置项里面发现使用了autoprefixer插件给我们自动加前缀
  • 然后处理scss文件转成css交到css-loader
  • 最后通过style-loader挂载到我们的页面中

这里有一个新的知识点,pulgin-插件,这个暂时可以知道这么使用,因为我会在后面的系列中单独讲到这个核心概念。

({ overrideBrowserslist: ['last 15 versions'] }) 这个是我自己加上去的。

ok,我们再次打包之后,来看看我们的页面中已经为我们自动生成了前缀。

样式篇补充

首先我们来假设这样一个场景

  1. 我现在在css.js中引入index.scss
  2. 然后在index.scss中@import './other.scss'

在打包过程中,他先走postcss-loader,然后走sass-loader,但在遇到@import其他scss文件的时候可能就不会重新走postcss-loader,sass-loader了,那这个时候我们又应该怎么办呢?

// importLoaders 
use: [
  'style-loader',
  {
    loader: 'css-loader',
    options: {
      importLoaders : 2 // 通过import引入的scss文件,也要走下面两个loader
    }
  },
  'sass-loader',
  'postcss-loader'
]
复制代码

这样就能保证无论是在scss中还是页面中import的scss文件,都会重新顺序执行loader.

模块化打包

我们在dist目录下新建m.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模块化打包</title>
</head>
<body>
  <div id="root"></div>
</body>
<script src="./main.js"></script>
</html>
复制代码

在src下新建m1.js/m2.js

// m1.js
import avatar from '../statics/images/aa.jpeg'
import createAvatar from './m2'
import '../statics/style/index.scss'

createAvatar()

var img = new Image
img.src = avatar
img.classList.add('avatar')
var root = document.getElementById('root')
root.append(img)

// m2.js
import avatar from '../statics/images/aa.jpeg'

export default function createAvatar(){
  var img = new Image
  img.src = avatar
  img.classList.add('avatar')
  var root = document.getElementById('root')
  root.append(img)  
}
复制代码

m2中有一个方法创建图片,那么我们每次调用一次就会创建一个图片,然后在m1中引入了index.scss样式。这样的话,m1的样式文件就会作用于我当前引入的页面标签,还会作用于m2我自己封装的创建函数中,所以这样引入的方式,样式相当于是全局的。

css打包模块化概念

如果描述我们的代码就会变得很糟糕,所以我们需要开启css打包的模块化概念

在webpack.config.js中开启css的模块化打包

modules: true
复制代码

然后我们还会在引入方式中做出改变。

// m1.js
import style from  '../statics/style/m.scss'

img.classList.add(style.avatar)

// m.scss
.avatar{
  width: 100px;
  height: 100px;
}
复制代码

在打包就不会出现刚才的问题,这个时候就之后m1中图片的样式生效了。这样就只会有一个图片样式生效。

如果你想要在创建的文件里也生效。那么用同样的方式处理即可。

打包字体文件

字体图标库在近几年的网站中运用的已经越来越广泛了。所以在很多项目中都会用到一些图标来装饰我们的网站,其中阿里图标库就做的相当不错。

  1. 我们随便的选取一些下载至本地。然后运用到我们的项目当中。然后在statics中新建fonts文件夹,讲字体文件全部放进去。

  2. 新建font.scss,将下载的iconfont.css内容拷贝进去,需注意文件路径

@font-face {font-family: "iconfont";
  src: url('../fonts/iconfont.eot?t=1590298271844'); /* IE9 */
  src: url('../fonts/iconfont.eot?t=1590298271844#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
  url('../fonts/iconfont.woff?t=1590298271844') format('woff'),
  url('../fonts/iconfont.ttf?t=1590298271844') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('../fonts/iconfont.svg?t=1590298271844#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-biaoqing:before {
  content: "\e63d";
}

.icon-biaoqing1:before {
  content: "\e650";
}

.icon-biaoqing2:before {
  content: "\e62d";
}
复制代码
  1. 新建font.html/font.js
import '../statics/style/font.scss'

var root = document.getElementById('root')
root.innerHTML = '<div class="iconfont icon-biaoqing"></div>'
复制代码

这个时候都不用想,引入样式然后进去会找到字体文件,打包肯定失败,所以我们会继续进行配置字体文件的打包。

// 取消scss的模块化打包
// modules: true

// 利用file-loader将我的字体文件打包,并放在fonts目录下
{
    test: /\.(eot|svg|ttf|woff|woff2)$/, // 检测文件是vue结尾的
    use: {
      loader : 'file-loader',
      options: {
        outputPath: '/fonts/'
      }
    }
  },
复制代码

ok,这样就可以完美的运行了。

总结

loader我们的入门已经差不多了,回顾一下本节内容。

  1. 打包图片资源
  2. 打包css文件
  3. 打包scss文件,并@import打包,自动加前缀
  4. loader基本知识以及配置项讲解 输出路径等
  5. 字体打包等练习。

这里为大家推荐官方的打包讲解,以及对数据之类的打包方案等。webpack资源管理

如果这篇文章对您有帮助,还请为我的努力点个赞,下一节我们将会认识webapck的插件(plugin)。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!