要理解publicpath,先要理解资源是如何被打包的
资源打包
1. 新建项目
我们新建一个项目,目录结构如下
drwxr-xr-x 5 huangyue staff 160 4 25 18:31 dist
drwxr-xr-x 661 huangyue staff 21152 4 25 16:59 node_modules
-rw-r--r-- 1 huangyue staff 288585 4 25 16:59 package-lock.json
-rw-r--r-- 1 huangyue staff 500 4 25 16:59 package.json
drwxr-xr-x 5 huangyue staff 160 4 25 17:49 src
-rw-r--r-- 1 huangyue staff 674 4 25 18:33 webpack.config.js
webpack.config.js
如下
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'file-loader'
}
}
]
}
};
2.创建文件
- 在src下新建一个
index.js
,style.css
和image目录,image目录里放入一个名为icon.png
的图片
➜ src ll
total 16
drwxr-xr-x 3 huangyue staff 96 4 25 17:49 image
-rw-r--r-- 1 huangyue staff 499 4 25 17:54 index.js
-rw-r--r-- 1 huangyue staff 67 4 25 17:49 style.css
➜ src ll image
total 240
-rw-r--r--@ 1 huangyue staff 120422 4 25 17:49 icon.png
style.css
引用了图片
.hello {
background: url('./image/icon.png');
}
index.js
导入了css文件
import _ from 'lodash';
import './style.css';
function component() {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
return element;
}
document.body.appendChild(component());
- 在dist下新建一个
index.html
,引用打包后的bundle.js
<!doctype html>
<html>
<head>
<title>Getting Started</title>
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
3.打包
用webpack打包后,dist里文件如下
➜ dist ll
total 408
-rw-r--r-- 1 huangyue staff 120422 4 25 19:43 57b42c57c9cba554ddf4b7a64a1b63b8.png
-rw-r--r-- 1 huangyue staff 78020 4 25 19:43 bundle.js
-rw-r--r--@ 1 huangyue staff 136 4 25 16:11 index.html
可以看出:
- js文件打包到了output.path + output.filename
文件里
- css文件没有被创建,因为它直接被style-loader
加进了html文件里(其实是写进了js里,然后js执行时再写入html里)
- 图片文件打包到了output.path
目录下,名字换成了hash值,当然可以自己定义名字
我们访问以下index.html,发现css生效了,图片也正确的引用了。用f12调试,可以发现在<head>
标签里插入了css代码:
.hello {
background: url(57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
可以看出:
- file-loader
把css文件里的图片引用改了,以前是'./image/icon.png'
,现在改成了57b42c57c9cba554ddf4b7a64a1b63b8.png
- 无论是名称还是相对路径都改了。
但是,这个相对位置是相对谁呢??
- 是相对与index.html的位置吗?
- 是相对于打包后的bundle.js
的位置吗?
- 还是相对于output.path
的位置呢?
由于目前index.html,bundle.js,output.path的目录是一样的,所以需要一个个分析
分析打包后的路径
1.首先,看看是不是与index.html的位置有关,很简单,我们把index.html移到项目根目录下并修改js引用
<script src="./dist/bundle.js"></script>
➜ test ll
total 592
drwxr-xr-x 5 huangyue staff 160 4 25 19:56 dist
-rw-r--r-- 1 huangyue staff 146 4 25 19:56 index.html
drwxr-xr-x 661 huangyue staff 21152 4 25 16:59 node_modules
-rw-r--r-- 1 huangyue staff 288585 4 25 16:59 package-lock.json
-rw-r--r-- 1 huangyue staff 500 4 25 16:59 package.json
drwxr-xr-x 5 huangyue staff 160 4 25 17:49 src
-rw-r--r-- 1 huangyue staff 678 4 25 19:57 webpack.config.js
如果打包后图片的路径是相对于index.html
生成的,那么由于图片在dist文件夹下,图片的引用就会是
./dist/57b42c57c9cba554ddf4b7a64a1b63b8.png
让我们访问现在的index.html,很不幸,发现图片没有被正确加载,f12看看
.hello {
color: red;
background: url(57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
图片的引用并未改变,说明引用图片的相对路径与index.html无关
2.那是不是与bundle.js
有关呢?很简单,我们接着上一步,改一改bundle.js
的位置
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'dist')
},
这样index.html的js引用也稍微改改
<script src="./dist/js/bundle.js"></script>
如果图片的相对位置是与bundle.js
关联的,那么图片的引用就会是
../57b42c57c9cba554ddf4b7a64a1b63b8.png
打包,看结果,图片依旧没有被加载,f12看一下:
.hello {
color: red;
background: url(57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
没有变化
3.那么相对路径就只能是与output.path
相关咯。为了验证这个,我们改一改配置文件
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
outputPath: 'images'
}
}
}
这里加了一个outputPath: 'images'
,目的是使得图片文件会在dist
的images
文件夹下生成
打包看看效果
➜ dist ll
total 8
drwxr-xr-x 3 huangyue staff 96 4 25 20:22 images
drwxr-xr-x 3 huangyue staff 96 4 25 19:56 js
➜ dist ll images
total 240
-rw-r--r-- 1 huangyue staff 120422 4 25 20:22 57b42c57c9cba554ddf4b7a64a1b63b8.png
在f12调试一下index.html
.hello {
color: red;
background: url(images/57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
可以看到,图片引用的路径变了!正好就是相对于output.path
的路径。
另外
file-loader的这种加载资源的特性,不仅仅是针对于这次实验里的css引用,所有通过file-loader加载的资源都是一样。
比如在js里引用的图片,引用路径也会做更改
言归正传
前面讲了那么久的图片打包,其实是为了更好的理解publicPath
。
正如上面的实验一样,因为图片引用的路径是相对于output.path
的,假如我index.html没有放在output.path
底下,图片引用路径就错了。
这种情况下,就该使用publicPath
了。
先稍微回顾一下现在的目录机构
➜ test ll
total 592
drwxr-xr-x 5 huangyue staff 160 4 25 20:22 dist
-rw-r--r-- 1 huangyue staff 146 4 25 19:56 index.html
drwxr-xr-x 661 huangyue staff 21152 4 25 16:59 node_modules
-rw-r--r-- 1 huangyue staff 288585 4 25 16:59 package-lock.json
-rw-r--r-- 1 huangyue staff 500 4 25 16:59 package.json
drwxr-xr-x 5 huangyue staff 160 4 25 17:49 src
-rw-r--r-- 1 huangyue staff 674 4 25 20:28 webpack.config.js
➜ test ll dist
total 8
drwxr-xr-x 3 huangyue staff 96 4 25 20:22 images
drwxr-xr-x 3 huangyue staff 96 4 25 19:56 js
而目前的图片引用路径为
.hello {
color: red;
background: url(images/57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
明显,如果要正确引用到图片,还要再加一层dist
目录。所以,修改配置文件如下:
output: {
filename: 'js/bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: './dist/'
},
加上了publicPath
打包,访问index.html
,发现图片已经加载了,f12看看:
.hello {
color: red;
background: url(./dist/images/57b42c57c9cba554ddf4b7a64a1b63b8.png);
}
可以看到,引用的路径是publicPath + 图片相对于output.path
的路径
那么,publicPath
到底是干啥用的,就已经比较明白了。