1. Webpack 的 loader
1.1 问题引入
之前的我的项目中咱们打包的对象都是 JS 文件,那假如咱们须要 import 一个图片应该怎么做呢,如果依然应用之前的形式进行打包就会报错:
Module parse failed:Unpexpected character ...
很显著 webpack 不能辨认图片文件,这里就须要借助 loader 来通知 webpack 如何打包图片文件了
1.2 loader 是什么
Loader 就是一种打包计划,对于某一种类型文件他晓得如何打包,帮忙 webpack 实现打包工作。
如果你写过 vue,必定写过相似的语句
import Header from './header.vue'
1.3 配置文件批改以引入 loader
咱们须要给之前的 webpack 配置文件中退出一个 module 字段,并新增一个 rules 数组来减少规定:
const path = required('path')
module.exports = {
mode:'development',
entry:{main:'./src/index.js'},
module:{
rules:[{
test:/\.jpg$/,
use:{loader:'file-loader}
}]
},
output:{...}
}
上述其实就是制订了一个规定,通知 webpack 遇到以.jpg 结尾的文件时候应用 file-loader 去解决。
这里别忘了先把 file-loader 装置到我的项目中:
npm install file-loader -D
这样从新 npm run bundle 就能够看到 dist 目录上面多出了一个图片文件。
file-loader 底层做了这些:当他发现你这边图片文件要打包,首先会把图片挪动到 dist 目录上面去 并改一个名字(名字能够本人定义),而后会失去图片绝对于 dist 目录的一个名称,而后返回给引入模块的变量之中。
file-loader 实践上能够解决任何动态资源,例如 excel,jpg,png,他实际上就是挪动地位而后把新地址返回给变量,只有你的 test 字段写好就能够。
借助这一点咱们尝试把动态资源放到网页上:
import avatar from './avatar.jpg'
const img = new Image();
img.src = avatar;
....
root.append(img)
1.4 loader 打包动态资源 - 图片
这里咱们持续扩大之前的内容,理解如何对 loader 进行一些自定义配置和应用。
放弃图片原名
默认应用 file-loader 会更改图片文件名称,然而咱们心愿放弃原名该怎么做呢?
这里能够通过对该 loader 进行配置解决:
...
module:{
rules:[{
test:/\.jpg$/,
use:{
loader:'file-loader',
options:{name:'[name].[ext]' // 记得包单引号
}
}
}]
}
...
这里的 [name],[ext] 是 loader 提供的占位符,具体 value 能够参考对应 loader 的文档,上述 name 和 ext 别离示意解决文件的名称和后缀
打包其余类型图片
大家应该联想到解决办法了,间接批改 test 字段匹配到更多的图片类型即可:
test:/\.(jpg|png|gif)$/
心愿图片资源打包后寄存在一个独自目录
这里能够再增加一个 outputPath 配置项:
use:{
loader:'file-loader',
options:{
name:...
outputPath:'images/'
}
}
url-loader 与 file-loader 区别
这里你可能会在其余 webpack 材料外面看到应用 url-loader 来对图片进行打包。
这里目前来说 url-loader 是能够代替 file-loader 来打包图片文件。
区别在于 url-loader 是将图片转换为 base64 寄存在 bundle.js 文件中,而非放到 dist 目录下。
file-loader 的特点:
- 能够指定要复制和搁置资源文件的地位,以及如何应用版本哈希命名以取得更好的缓存。
- 你能够就近治理图片文件,能够应用相对路径而不必放心部署时 URL 的问题。
- 应用正确的配置,webpack 将会在打包输入中主动重写文件门路为正确的 URL。
url-loader 的特点:
- 容许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值),这会缩小小文件的 HTTP 申请数。
- 如果文件大于该阈值,会主动的交给 file-loader 解决。
最佳实际
目前的最佳工夫就是应用 url-loader 将一些几 KB 的小图片打包到 JS 文件中,而大图片挪动到 dist 目录下,保障 bundle.js 尽快加载实现。
这里你须要配置的就是一个阈值,保障不同区间应用不同策略:
use:{
loader:'url-loader',
options:{
...
limit:2048
}
}
上述示意小于 2KB 的会打包到 bundle,否则就利用 file-loader 挪动到 dist 目录
1.5 loader 打包动态资源 - 款式
我的项目中通常都会有 css 文件负责管理款式,间接 webpack 打包同样无奈解析,须要利用 loader 来解决。
应用 style-loader 与 css-loader
这里咱们针对 css 文件新增一个 rule 并应用对应 loader 来解析
module:{rules:[{...},{
test:/\.css$/,
use:['style-loader','css-loader']
}]
}
而后 npm 装置一下之后浏览器就能够失常显示了。
接着咱们阐明一下这两个 loader 的作用。
css-loader 会帮忙咱们剖析多个 css 文件之间的关系,而后把多个 css 文件合并成一个 css。
style-loader 会将上述合并后的 css 文件挂载在文件的 header 下面:
<head>
...
<style>.avatar{width:150px;}
</style>
...
</head>
所以在应用 css-loader 时候须要配合 style-loader 来应用才行
款式中前缀的补足
咱们能够应用 postcss-loader 来补足款式中诸如 webkit 这种前缀,默认打包是没有的:
transform: webkit-translate(100px,100px)
这个 loader 还要求咱们在目录下创立一个 postcss.config.js 文件,这里对其进行一些配置:
//postcss.config.js
module.exports = {
plugins:[require('autoprefixer')
]
// 应用了一些插件
}
须要执行 npm install autoprefixer - D 来装置插件。而后从新进行一次打包
scss 的解决
这里咱们能够先写一个有 scss 非凡语法的文件:
body{
.avatar{...}
}
这里间接批改 test 匹配规定也是没用的,最终会发现页面挂在的还是 scss 语法的 style,没有进行解析:
<style>
body{
.avatar{...}
}
</style>
这里还须要借助 sass-loader 来解决,这里还须要装置 node-sass 模块来进行解析(这部分官网文档有阐明):
npm install sass-loader node-sass -D
less 的解决
less 须要应用 less-loader,具体应用形式和上述相似
1.6 css-loader 的进阶配置
这里持续扩大讲一下 css-loader
importLoaders
该配置参数用于 css 中的一些间接援用的状况:
{
test:/\.scss$/,
use:[
'style-loader',
{
loader:'css-loader',
options:{importLoaders:2}
},
'sass-loader',
'postcss-loader'
]
}
咱们在一个 index.scss 文件外面引入一个新的 scss 文件:
// index.scss
@import './avatar.scss'
...
这个时候其实是 index.js 援用了 index.scss,间接援用了 avatar.scss,这个时候你引入的 scss 就有可能不会应用上面的 postcss-loader 和 sass-loader 了,如果你心愿间接援用的也实用这些 loaders,就须要这个配置项,importLoaders:2 意味着无论间接援用还是间接援用都会从下到上再应用 2 个 loader!
CSS 模块化
上述配置的 CSS 其实是全局共享的,这样很容易导致款式抵触,咱们能够配置来保障 CSS 只在 import 引入的 JS 文件中起作用:
{
test:/\.scss$/,
use:[
'style-loader',
{
loader:'css-loader',
options:{
importLoaders:2,
modules:true
}
},
'sass-loader',
'postcss-loader'
]
}
1.7 loader 打包动态资源 - 字体
这里有时候咱们心愿我的项目能展现一些第三方字体,就须要引入字体文件,基于上述打包图片和款式的思路,咱们其实间接借助 file-loader 就行了:
{test:/\.(eot|ttf|svg)$/,
use:{loader:'file-loader'}
}
1.8 loader 的程序
module:{rules:[{...},{
test:/\.css$/,
use:['style-loader','css-loader','sass-loader']
}]
}
留神 webpack 外面 use 的 loader 是有先后顺序的,从下倒上,从右到左,例如下面的例子当中咱们是先执行 sass-loader,把 scss 转成 css,而后 css-loader 打包为一个 css,最初 style-loader 进行挂载
2.Webpack 的 plugin
loader 次要是解析不同类型的文件,而 plugin 则是提供一些额定的性能。
其实 plugin 能够在 webpack 运行到某个时刻的时候帮你主动做一些事件,有些相似 React 或 vue 生命周期函数的概念~
官网举荐的 webpack 插件有几十个,还有很多第三方插件也有很多性能,没必要一个个学,当咱们想实现一些性能能够先搜寻,找找有没有不便的插件或者配置
2.1 HtmlWebpackPlugin 介绍
这里咱们心愿解决一个理论问题,之前咱们的 dist 目录下的 HTML 文件其实都是手动拷贝过来的,有没有工具能主动实现这个。
这里就能够借助 html-webpack-plugin,首先 npm install 一下:
npm install html-webpack-plugin -D
接着咱们在配置文件中引入 plugin:
module.exports = {
mode:'development',
entry:{...},
module:{rules:[...]
},
plugins:[new HtmlWebpackPlugin()],
output:{...}
}
接着咱们从新打包,该插件会在打包完结之后主动生成一个 html 文件,并主动蕴含对应的 JS 文件。
然而咱们会发现界面下面啥也没有,这是因为咱们之前的代码逻辑是找到 id 为 root 的 DOM 节点,而后插入一个 div 节点,然而打包生成的没有这个 root。
配置 plugin
这里咱们能够通过编写一个 template 文件,来用作插件主动生成的 HTML 文件的模板:
...
<body>
<div id='root'></div>
</body>
而后咱们配置:
plugins:[new HtmlWebpackPlugin({template:'src/index.html'})]
接着从新打包就会生成蕴含 root 节点的的 index.html
2.2 CleanWebpackPlugin 介绍
有时候咱们批改了一下 output 的文件名,然而打包之后咱们发现有新的 dist.js 文件了,然而 bundle.js 文件还在,没有删除,咱们心愿可能把 dist 目录删除而后再执行打包工作,这时候就能够用这个插件。
留神这个插件不是官网举荐插件,官网搜不到,这里间接装置:
npm install --save-dev clean-webpack-plugin
而后增加到 plugins 数组:
plugins:[new HtmlWebpackPlugin({...}),
new CleanWebpackPlugin(['dist'])
]
参数是要删除的目录名