问题
修改完脚手架,在本地测试时,发现了一个问题,当时使用这样一段代码:
<template> <view class="content"> <image class="logo" src="../../static/logo.png"></image> ... </view> </template>
在配置好publicPath
后,将dist/build/h5
的结果上传到我们的静态服务器上后,发现图片显示不出来。在控制台检查一下代码,发现此处的img
标签是这样的:
也就是说配置的publicPath
并未生效。
寻找解决办法
开始怀疑是不是自己漏掉了什么配置,在uni-app
找了关于image
组件的使用方法,里面看起来并没有什么特殊的说明。好吧,Google一下,发现网上有一些解决方案,需要把代码改成下面这样:
<template> <view class="content"> <image class="logo" :src="require('../../static/logo.png')"></image> ... </view> </template>
试了一下,确实,图片回来了:
但是这样解决还是略有些简陋,改脚手架不能止步于此。于是继续寻找解决办法
思路
迅速的捋一下思路,出现这个问题的原因是,.vue
文件在编译阶段并没有为这个image组件的src属性的值自动加上require
,从而无法被file-loader或url-loader来正确的处理。看来问题的关键就出在编译.vue
文件这里。
所以去看了一下vue-loader的官方文档,vue-loader的文档很明显的有专门的一节来介绍这个功能:
大概意思就是说有一个transformAssetUrls
的属性可以用来处理这种问题。这个属性的默认值是:
{ video: ['src', 'poster'], source: 'src', img: 'src', image: ['xlink:href', 'href'], use: ['xlink:href', 'href'] }
也就是说,vue-loader默认会处理比如img
标签的src
属性,如果src
的值为相对路径,就会将其替换为require(...)
调用。去看一下uni-app
的脚手架是怎么配vue-loader便知。直接去node_modules下看源码,找到配置vue-loader的地方在@dcloudio/vue-cli-plugin-uni/lib/h5/index
里:
// @dcloudio/vue-cli-plugin-uni/lib/h5/index.js#L113 webpackConfig.module .rule('vue') .test([/\.vue$/, /\.nvue$/]) .use('vue-loader') .tap(options => Object.assign(options, { compiler: getPlatformCompiler(), compilerOptions: require('./compiler-options'), cacheDirectory: false, cacheIdentifier: false })) .end() // ...
在.tap
中发现,uni-app
的脚手架并没有配置transformAssetUrls
这个属性,可能只是走了默认的配置。直接在本地修改一下试试吧,直接修改node_modules/@dcloudio/vue-cli-plugin-uni/lib/h5/index
,试着为image增加一个src
属性:
// @dcloudio/vue-cli-plugin-uni/lib/h5/index.js#L113 webpackConfig.module .rule('vue') .test([/\.vue$/, /\.nvue$/]) .use('vue-loader') .tap(options => Object.assign(options, { compiler: getPlatformCompiler(), compilerOptions: require('./compiler-options'), cacheDirectory: false, cacheIdentifier: false, // 新增的这里 transformAssetUrls: { 'image': ['xlink:href', 'href', 'src'] } })) .end() // ...
发现并没有生效,仔细察看build后的源码,发现实际上image
组件最终会被处理成以渲染函数的形式来创建的组件:
// ... return createElement("v-uni-image", { staticClass: "logo", attrs: { src: '../../static/logo.png' } }) // ...
可以看到,组件名会被修改为v-uni-image,所以上面的配置才没有生效。
解决
继续改成这样:
// @dcloudio/vue-cli-plugin-uni/lib/h5/index.js#L113 webpackConfig.module .rule('vue') .test([/\.vue$/, /\.nvue$/]) .use('vue-loader') .tap(options => Object.assign(options, { compiler: getPlatformCompiler(), compilerOptions: require('./compiler-options'), cacheDirectory: false, cacheIdentifier: false, // 新增的这里 transformAssetUrls: { 'v-uni-image': 'src' } })) .end() // ...