加载图片
使用file-loader
file-loader可以将css和js文件里面的导入图片语句替换成正确的地址,同时将文件输出到正确的位置
module.exports = {
module: {
rules: [
{
test: /\.png$/,
use: ['file-loader']
}
]
}
}
使用url-loader
url-loader可以经过base64编码后注入js或css里面
url-loader会将根据图片内容计算出的base64编码的字符串直接注入代码中。由于一般的图片数据量巨大,会导致JavaScript/css文件也跟着变大,所以在使用url-loader时,一定要注意图片的体积不能太大,不然会导致因JavaScript/css文件过大而带来的网页加载缓慢问题。
一般啥时候用到呢,一般用它将网页需要用到的最小资源注入到代码中来减少加载次数(http/1协议中,每加载一个资源都会建立一个http链接,为了很小的资源而建立一次链接不划算)
所以!!! url-loader考虑到了以上问题,井提供了一个方便的选择:limit,该选项用于控制在文件的大小小于limit时才使用url-loader,否则使用fallback选项中配置的loader
module.exports = {
module: {
rules: [
test: /\.png$/,
use: [{
loader: 'url-loader',
options: {
// 30KB以下的文件采用url-loader
limit: 1024 * 30,
// 否则采用file-loader,默认值是file-loader
fallback: 'file-loader'
}
}]
]
}
}
其他优化
- 通过imagemin-webpack-plugin压缩图片
- 通过webpack-ritesmith插件制作雪碧图
加载SVG(矢量图的一种标准格式)
svg的使用方法和png等一样,所以也可以使用file-loader/url-loader 介绍其他loader的使用:
使用raw-loader
raw-loader将文本的内容读取出来注入到css/js文件中
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: ['raw-loader']
}
]
}
}
由于raw-loader会直接返回SVG的文本内容,并且无法通过css展示SVG的文本内容,因此采用本方法后无法在css中导入SVG,也就是说,在css中不可以出现
background.image:url (./svgs/activity.svg)这样的代码,因为background-image: url (<svg>...</svg>)是不合法的
使用svg-inline-loader
和raw-loader相似,不同之处在于svg-inline-loader会分析SVG的内容,去除其中不必要的部分代码,以减小SVG的文件大小。(即增加了对SVG的压缩功能)
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: ['svg-inline-loader']
}
]
}
}
加载Source Map
控制Source Map输出的Webpack配置项是devtool devtool选项列表
| detool | 含义 |
|---|---|
| 空 | 不生成Source Map |
| eval | 每个module会封装到eval里包裹起来执行,并且会在每个eval 吾句的末尾追加注释// # sourceURL=webpack:/// ./main.js |
| source-map | 会额外生成一个单独的Source Map文件,并且会再js文件的末尾追加// #sourceMappingURL=bundle.js.map |
| hidden-source-map | 和source-map类似,但不会再js文件末尾追加// #sourceMappingURL=bundle.js.map |
| inline-source-map | 和source-map类似,但不会额外生成一个单独的Source Map文件,而是将Source Map转换成base64编码内嵌到js中 |
| eval-source-map | 和eval类似,但会将每个模块的Source Map转换成base64编码内嵌到eval语句的末尾,例如// #sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW... |
| cheap-source-map | 和source-map类似,但生成的Source Map文件中没有列信息,因此生成速度更快 |
| cheap-module-source-map | 和cheap-source-map类似,但会包含Loader生成的Source Map |
以上知识devtool可能取值的一部分,他的取值可以由cource-map,eval,inline,hidden,cheap,module等六个关键字随意组合完成
- eval:用eval语句包裹需要安装的模块
- source-map:生成独立的Source Map文件
- hidden:不在js文件中指出Source Map文件的所在,这样浏览器就不会自动加载Source Map
- inline:将生成的Source Map文件转换成base64格式内嵌再js文件中
- cheap:在生成的Source Map中不会包含列信息,这样计算量更小,输出的Source Map文件更小,同时Loader输出的Source Map不会被采用
- module:来自Loader的Source Map被简单处理成每行一个的模块
如何选择(毕竟那么多组合)
如果不关心细节和性能,只是想在不出任何差错的情况下调试源码,则可以直接设置成source map,但这样会造成以下两个问题。
- 在source-map模式下会输出质量最高且最详细的Source Map,这回造成构建速度缓慢,特别是在开发过程中需要频繁修改时会增加等待时间
- 在source-map模式下会将Source Map暴露,若构建发布到线上的代码的Source Map暴露,就等同于源码被泄漏
为了解决以上两个问题:
- 在开发环境下将devtool设置成cheap-module-eval-source-map,因为生成这种Source Map的速度最快,能加速构建,由于在开发环境下不会做代码压缩,所以在Source Map中即使没有列信息,也不会影响断点调试
- 在生产环境下将devtool设置成hidden-source-map,生成最详细的Source Map,但不会将Source Map暴露出去,由于在生产环境下会做代码压缩,一个js文件只有一行,所以需要列信息。
生产环境下通常不会把Source Map上传到HTTP服务器让用户获取,而是上传到js错误收集系统,在错误收集系统上根据Source Map和收集到的js运行错误堆栈,计算出错误所在远吗位置 不要在生产环境下使用inline模式的Source Map,这回导致js文件变得很大,且会泄漏源码
加载现有的Source Map
某些从Npm安装的第三方模块是采用ES6或者TypeScript编写的,它们在发布时会同时带上编译出来的JavaScript文件和对应的Source Map文件,以方便我们在使用它们出问题时进行调试
在默认情况下,Webpack不会加载这些附加的Source Map文件,Webpack只会在转换的过程中生成Source Map。这时需要使用source-map-loader让 Webpack 加载这些附加的 Source Map 文件
module.exports = {
module: {
rules: [
{
test: /\.js$/,
// 只加载我们关心的目录下的Source Map,以提升构建速度
indlude: [path.resolve(root, 'node_modules/some-components/')],
// 将source-map-loader执行顺序放在最前面,怕再source-map-loader之前有loader转换了该js文件,会导致Source Map映射错误
enforce: 'pre'
}
]
}
}