webpack中img标签的src使用相对路径的方法

3,762 阅读3分钟

简介

Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。

webpack目前已经是大部分前端项目打包工具的首选,但是在使用的过程中还是存在一些问题。我们下面要讲到的就是常见的关于图片路径的问题。

tips: 解决方案在最后一节

img的src问题及其原因

在webpack项目中,如果要直接使用 img 的 src 属性来引用图片,由于webpack对html中图片的相对路径的处理方式的问题发现图片并不能正确的引用。webpack对图片的处理方式如下:

官方文档

默认情况下,vue-loader 使用 css-loader 和 Vue 模版编译器自动处理样式和模版文件。在编译过程中,所有的资源路径例如 <img src="...">、background: url(...) 和 @import 会作为模块依赖。

例如,url(./image.png) 会被转换为 require('./image.png'),而

<img src="../image.png">

将会编译为:

createElement('img', { attrs: { src: require('../image.png') }})

常见的解决方案及不足

在日常的项目中,如果某处样式需要使用图片,那我们常见的处理方法一般有几种:

1、 使用css background 来使用图片
不足:需要使用其他标签来替换img标签

.img {
  background-image: url('../assets/test.png');
}

这种方式一般webpack的配置中有使用 url-loader 来处理图片资源,小于一定尺寸的图片会被编译成base64内嵌在样式中。正常的图片都会被正确的打包到指定文件夹。

2、 使用 require 的方式引入图片,并将其动态绑定到src上面。
不足:需要没张图片都使用require引入
例如:

<img :src="imgs[0].src" />
data () {
  return {
    imgs: [{
      src: require('../assets/test.png')
    }]
  }
}
...

3、 使用图床,提前将图片资源上传至服务器,src中直接使用图床的图片地址即可。
不足:需要搭建图床,并且也可能存在测试环境和生产环境地址不一的问题

修改webpack配置,直接使用相对路径

在某些时候,我们必须要使用img标签,那么这时候,我们只能采用上面方案中的第2或3种,第2种的代码略显臃肿,第3种又需要构建图床。如果对于 webpack 的url-loader 的文档有仔细阅读的话我们可以发现通过修改webpack配置完全可以支持我们在src中直接使用相对路径。

{
  test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        limit: 1024 * 4,
        esModule: false,
        fallback: {
          loader: require.resolve('file-loader'),
          options: {
            name: `img/[name].[hash:8].[ext]`
          }
        }
      }
    }
  ]
},

这种方式会将我们在src中的图片复制到打包后文件夹下的img文件夹内并添加hash值,这时候我们在代码中就可以直接使用相对路径了。例如:

<img src="../assets/test.png" />