我们先尝试一下直接引入图片然后打包项目,看看是什么情景
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 解决没有favicon.ico时报错GET http://localhost:9999/favicon.ico 404 (Not Found) -->
<link rel="shortcut icon" href="#" />
<title>webpack学习</title>
</head>
<body>
<div>这是webpack学习</div>
<div id="root"></div>
<script src="./dist/main.js"></script>
</body>
</html>
index.js
const starImg = require('./src/assets/star.png');
const dom = document.getElementById('root');
const imgBox = new Image();
imgBox.src = starImg;
dom.append(imgBox);
webpack.config.js
const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块
module.exports = {
// entry: './index.js', // 指定当前目录的index.js为打包的入口文件
entry: {
main: './index.js', // 指定当前目录的index.js为打包的入口文件
// 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
// sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
},
mode: 'development', // mode 指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
// development默认配置了sourcemap
// development默认无tree shaking配置,需要额外配置
output: {
// filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
// chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
// path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
// 整体路径为第一个参数+第二个参数,即__dirname + dist
// 是所有输出文件的目标路径(物理路径, 存储路径);
publicPath: '/' // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
// 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
// (文件引用路径就是看这个)
// 是对页面引入资源的补充,比如img标签引入或者css引入等.
// 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
// publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
}
}
package.json
{
"name": "01_why_use",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"bundle": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
执行npm run bundle
打包结果如下,报错了,提示我们需要通过一个loader来处理star.png图片
在编写前端页面的时候,我们总是时常需要引入一些图片进行展示,那么如何利用webpack将图片打包进我们的项目中呢?
webpack默认是可以处理js文件的,但是它不能直接处理jpg,gif,png图片等静态资源,因此我们需要可以处理jpg,gif,png图片等静态资源的loader
loader就是一个打包方案,对于特定文件,loader可以告诉webpack如何打包这些文件,webpack不识别非js结尾的文件,就需要loader告诉webpack如何打包这些文件(如果需要打包的文件不是以js为后缀,就要考虑使用loader了)
在更高层面,webpack的loader有两个属性
test属性:用于标识出应该被对应的loader进行转换的某个或某些文件
use属性:表示进行转换时,应该使用哪个loader
我们可以通过url-loader或者file-loader进行图片的打包处理,这里我们以url-loader为例
npm i url-loader file-loader -D
webpack.config.js
const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块
module.exports = {
// entry: './index.js', // 指定当前目录的index.js为打包的入口文件
entry: {
main: './index.js', // 指定当前目录的index.js为打包的入口文件
// 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
// sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
},
mode: 'development', // mode 指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
// development默认配置了sourcemap
// development默认无tree shaking配置,需要额外配置
module: {
rules: [
{
test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
use: {
loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
options: {
name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
outputPath: 'images/', // 文件存储路径(output.path + 值)(物理路径, 存储路径)
// 负责输出目录, 即打包后的写在磁盘的位置
}
}
},
]
},
output: {
// filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
// chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
// path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
// 整体路径为第一个参数+第二个参数,即__dirname + dist
// 是所有输出文件的目标路径(物理路径, 存储路径);
publicPath: '/' // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
// 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
// (文件引用路径就是看这个)
// 是对页面引入资源的补充,比如img标签引入或者css引入等.
// 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
// publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
}
}
const path = require('path'); // 由于webpack无法直接操作文件夹,所以需要引入node的path模块
module.exports = {
// entry: './index.js', // 指定当前目录的index.js为打包的入口文件
entry: {
main: './index.js', // 指定当前目录的index.js为打包的入口文件
// 实际上是 entry: './index.js' 的具体写法,main为打包的Chunk Name
// sub: './postcss.config.js', // 可以有多个入口文件,指定当前目录的postcss.config.js为打包的入口文件
},
mode: 'development', // mode 指定打包模式(development(不会被压缩),production(这个模式的话代码会被压缩))
// development默认配置了sourcemap
// development默认无tree shaking配置,需要额外配置
module: {
rules: [
{
test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
use: {
loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
options: {
esModule: false, // 新版本中esModule默认为true,会导致图片的地址变为[object Module],因此这里设置为false
name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
outputPath: 'images/', // 文件存储路径(output.path + 值)(物理路径, 存储路径)
// 负责输出目录, 即打包后的写在磁盘的位置
}
}
},
]
},
output: {
// filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
// chunkFilename: '[name].[contenthash].chunk.js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
filename: '[name].js', // 打包后输出的打包文件的文件名,根据entry的chunk name作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// filename: '[name].[chunkhash].js', // 打包后输出的打包文件的文件名,根据entry的chunk name + chunkhash(解决缓存不更新的问题)作为输出文件名(如果entry有多个入口文件时必须用占位符这样设置output.filename)
// chunkFilename: '[name].chunk.js', // 入口文件走filename,其他非入口文件是index.js引入(同步引入或者异步引入)的间接js文件(非入口文件),如果打包生成的间接js文件,是走chunkFilename
path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
// path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
// 整体路径为第一个参数+第二个参数,即__dirname + dist
// 是所有输出文件的目标路径(物理路径, 存储路径);
publicPath: '/' // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
// 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
// (文件引用路径就是看这个)
// 是对页面引入资源的补充,比如img标签引入或者css引入等.
// 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
// publicPath: 'http://www.cdn.cn' // 如果,想把打包后生成的index.html作为入口文件,而打包生成的js放到服务器上如http://www.cdn.cn,那么webpack就应该这样设置
}
}
重新npm run bundle打包
图片成功出现
但是发现打包生成的dist没有图片文件,这是怎么回事呢?
看一下打包生成的main.js,原来url-loader将图片转成了base64字符串,放到了main.js里
正常情况下,小图片我们为了减少http请求次数,可以将其打包进main.js里,但是如果图片过大,放到main.js反而会影响页面打开的速度,因此我们最好做一个限制,超出限制大小的图片,则将其打包到一个image文件夹里,未超出限制大小,则将图片转成base64打包进main.js里。url-loader恰好有这个功能
webpack.config.js增加url-loader的limit
rules: [
{
test: /\.(jpg|png|gif)$/, // 对文件类型后缀进行匹配
use: {
loader: 'url-loader', // 使用url-loader对图片进行打包,如果url-loader的options没有设置limit,默认将所有静态文件全部打包成base64的字符串放到js里
options: {
esModule: false, // 新版本中esModule默认为true,会导致图片的地址变为[object Module],因此这里设置为false
name: '[name]_[hash].[ext]', // 输出的文件名为[原名称]_[哈希值].[原后缀]
outputPath: 'images/', // 文件存储路径(output.path + 值)(物理路径, 存储路径)
// 负责输出目录, 即打包后的写在磁盘的位置
limit: 2048 // 限制当文件小于2KB的时候,就将文件转为base64存储于js中,以减少http请求次数,当文件大于2KB,则打包文件到指定目录,避免js过大
}
}
},
]
重新npm run bundle打包,可以看到dist目录生成了images目录和一张图片
但是打开index.html,提示图片路径出错了
上一篇文章webpack成长指北第5章—webpack的基础配置讲过,output.publicPath是对页面引入资源的补充,比如img标签引入或者css引入等,一般来说,如果打包本地资源报404,很有可能就是publicPath没设置正确导致的,我们修改一下webpack的output.publicPath
output: {
filename: '[name].[contenthash].js', // contenthash,根据content(代码内容)产生的hash值,如果代码不变,contenthash就不会变,否则就会变,主要为了解决浏览器缓存因为名字不变,更新代码后不重新请求更新后文件的问题
path: path.resolve(__dirname, 'dist'), // 指定打包后输出的打包文件在当前webpack.config.js所在文件夹的绝对路径的dist文件夹下
// path值必须是绝对路径 ,所以引入path包,__dirname代表当前webpack.config.js所在文件夹的绝对路径
// 整体路径为第一个参数+第二个参数,即__dirname + dist
// 是所有输出文件的目标路径(物理路径, 存储路径);
publicPath: './dist/' // (url 相对于 HTML 页面所在文件夹的绝对路径 + 值)给output配置全局的publicPath,
// 这样各个loader打包出来的文件发布路径(引用地址)就是此全局publicPath + loader的options.outputPath
// (文件引用路径就是看这个)
// 是对页面引入资源的补充,比如img标签引入或者css引入等.
// 千万不能设错,应该观察文件和HTML页面的存储地址位置,进行设置,否则引用时地址会错误,找不到文件
}