前面写了webpack打包js文件的方法,但打包图片资源又会用到什么的方法呢?本文就这个问题进行探讨学习。
本文的目的是使用webpack打包图片资源,并能够使打包后的图片显示在浏览器上。
首先,备好一张图片素材,我使用的是一张之前在网上下载过的手机图片,格式为jpg,当然,使用其他的格式如png、gif也是可以的,到时在配置文件里面更改响应的配置即可。
开始的时候目录长这样:
这是在安装好了webpack、webpack-cli,初始化了项目(npm init)、手动添加了webpck.config.js文件后的目录结构,如果没有这些,首先需要安装和初始化一下,我前面的文章也有写到,有需要的可以翻看我之前的文章。
跟之前不同的是,我添加了image.js文件,添加了图片素材。
接下来打开image.js文件进行代码编写,比较简单的一个功能,就是把图片引入到image.js,创建一个img标签,img标签的路径src为引入的图片,然后把img标签挂载到页面上。
Now show you the code:
image.js
import photo from './image/mz16th.jpg';
function Image () {
var dom = document.getElementById('root');
var img = document.createElement('img');
img.src = photo;
dom.append(img);
}
export default Image;
index.js
import Image from './image.js';
new Image();
webpack.config.js文件就是打包配置了,打包图片资源可以使用file-loader和url-loader,首先介绍的是file-loader,使用file-loader需要安装一下,使用本地安装,npm install file-loader --save-dev或者npm install file-loader -D,成功安装显示如下:
然后在module中进行file-loader的配置:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader'
}
]
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
mode为development表示模式为开发环境,entry是入口文件的配置,这里src目录下的index.js为主入口文件。module中是loader的相关配置。rules里面,use表示要使用的loader,test表示需要使用use中的loader进行解析的文件格式,这里针对jpg\png\gif这三种图片格式的图片进行解析。output是输出文件的配置,即打包后文件的名称和目录存放位置。这里指定打包后的对应entry中的main(./src/index.js)文件的文件名为bundle.js,目录存放在webpack.config.js文件所在目录中的dist文件夹里。
package.json文件做了scripts的配置
"scripts": {
"build": "webpack"
}
执行打包命令 npm run build后:
可以看到打包之后,图片直接打包到了dist目录下,与bundle.js输出文件同级。
但是还缺少一个文件,就是要在浏览器中打开的html文件,来到这一步,我踩了一个坑,就是直接把index.html文件创建在了与webpack.config.js同级的目录中。先看下index.html文件的内容:
index.html
Index
可以看到,script的src路径是这样的:.dist/bundle.js,原本以为这样没问题,但在浏览器中打开index.html文件,其实图片没有显示出来。这是什么原因呢?问题回到image.js文件中img标签的src上。上面我是写了img.src = photo,photo是什么呢?其实photo是打包后的图片名称,就是这个东西:bf6497991f776c6b098b105b056c6adc.jpg,显然,img标签直接引入了打包后图片的名称,但是img标签我是在webpack.config.js同级目录下的image.js文件中创建的,如果img.src = bf6497991f776c6b098b105b056c6adc.jpg就表示打包后的图片文件要与image.js文件同级。
进一步验证,可以打开bundle.js这个打包后的文件,查看:
可以看到,_image_jpg__WEBPACK_IMPORTED...这个东西并没有任何上层文件夹,img.rsc直接指向它,所以,要是index.html引入了这个bundle.js,index.html是无法在同级目录中找到打包后的图片文件的。
既然这样,那我可以改一下img.src = `./dist/${photo}`。再打一次包,查看bundle.js:
加上了./dist之后,打包后的bundle.js文件中的img.src也改变了。所以我在浏览器中也就可以看到图片显示了出来。
但如果要保存打包后的文件就放到dist目录中,src目录中的源代码文件就放到src中,有没有办法可以实现src访问dist的资源呢?我还在探索中...
目前想到的两个简单的方法是,要不就是index.html放到dist里,要不就是image.js文件中的src路径加上./dist。
这个先这样解决吧,遇到好的方法我再做调整。
但我不对image.js文件做修改,而是直接把index.html文件放到dist目录中。
在浏览器中依然可以显示出图片:
解决了图片显示的问题,接下来讲一下自定义打包图片的路径和文件名的方法。其实这两个配置也很简单,使用options的占位符配置可以做到:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
]
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
这个配置可以把打包后的文件名称保持与打包之前的文件名称一致。比如打包之前,图片名称是mz16th,那么打包后就不会线程一段乱码的文件名。
先把dist中的bundle.js和图片删除,保留index.html。然后打包,查看dist目录或者打包信息:
如果配上hash,则会打包成:
后面的hash就是之前的乱码的文件名称。
如果想要把打包后的图片资源统一放到dist里的指定的文件夹下,可以使用outputPath这个属性配置:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/'
}
}
]
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
然后打包。同样打包之前先把dist中的bundle.js和图片删除,查看打包后的dist文件:
除了使用file-loader来打包图片资源外,还可以使用url-loader来打包。不同之处在于,url-loader比较适合用来打包图片较小的文件,url-loader打包出来的图片是base64图片,而file-loader适合用来打包较大的图片,但是打包出来的图片不是base64。
为啥说url-loader适合打包较小的图片呢?因为url-loader把图片打包后,并不会在dist文件夹中多出打包后的文件,而是在打包后的bundle.js中引入了。所以如果图片较大的情况下,打包进了bundle.js里面,这会造成bundle.js文件过大,这时页面加载bundle.js会花费很多时间。
但解决这个问题的方法还是有的。使用url-loader的时候,配置一个limit属性,limit的值是一个数值,表示字节大小。如果超过某个指定的数值大小时,图片就放到dist目录下,像file-loader打包后那样,如果在limit值之内,就直接在bundle.js里引入。
使用url-loader也需要先安装。
webpack.config.js中,其他内容不变,把file-loader改成url-loader,然后再加上limit属性:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 400000
}
}
]
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
查看图片大小:
图片大小在limit范围内,所以打包后图片资源不会显示在dist文件夹下,而是被bundle.js引入了。
查看图片格式,这时是base64格式。
这时,我改变一下limit设置得小一点,然后再打包。
可以看到这时就会在dist目录下多了一个images。超过了limit的大小的文件就会放到dist下。
查看图片格式,这时的图片已不是base64。
以上分享了file-loader和url-loader的使用,他们的功能还是比较强大的,对于解析图片来说,但这个过程中我还是遇到了不懂的地方,之后如果有get到更好用的东西的话,再来补充。
-end-