理解webpack的publicPath

要理解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.创建文件

  1. 在src下新建一个index.jsstyle.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
  1. style.css引用了图片
.hello {
    background: url('./image/icon.png');
}
  1. 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());
  1. 在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',目的是使得图片文件会在distimages文件夹下生成

打包看看效果

➜  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到底是干啥用的,就已经比较明白了。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值