背景
最近在开发组件构建功能,将vue组件
构建为独立的js文件,用于被其他页面引用加载。
但是存在一个问题,html引用的图片路径正常来说要么是相对路径,要么是完整的绝对路径。
但是相对路径相对的是加载js的html页面,与js引用的图片资源路径毫无关系。又不能在构建之前决定加载js的publicPath前缀路径。
那么怎样实现js文件在任何地方加载,同时js相对路径的图片也被正常加载,是一个问题。
组件目录结构
├─dist
│ ├─Card-demo // 组件
│ │ ├─0.0.1 // 组件版本
│ │ │ ├─index.js // 组件js
│ │ │ ├─static
│ │ │ │ ├─icon.xxx.png
观察vue-cli
在之前的开发过程中,发现使用vue-cli的构建lib库的时候,发现无论在哪个页面加载js库,图片都能正常加载。而且html加载的图片居然都是完整路径,并且工程没有处理过publicPath公共资源路径。
非常好奇,查看一下vue-cli构建代码是怎么构建的。
vue-cli构建lib库使用的是vue-cli-service build --target lib xxx
命令。
构建代码在@vue\cli-service\lib\commands\build\resolveLibConfig.js
位置,发现一段关键注释:
rawConfig.output = Object.assign({
library: libName,
libraryExport: isVueEntry ? 'default' : undefined,
libraryTarget: format,
// preserve UDM header from webpack 3 until webpack provides either
// libraryTarget: 'esm' or target: 'universal'
// https://github.com/webpack/webpack/issues/6522
// https://github.com/webpack/webpack/issues/6525
globalObject: `(typeof self !== 'undefined' ? self : this)`
}, rawConfig.output, {
filename: `${entryName}.js`,
chunkFilename: `${entryName}.[name].js`,
// use dynamic publicPath so this can be deployed anywhere
// the actual path will be determined at runtime by checking
// document.currentScript.src.
publicPath: ''
})
意思为使用动态publicPath,这样就可以在任何地方部署。实际的路径将在运行时通过检查确定。
同时断点通过vue-cli的lib命令构建的库,图片生成路径逻辑,发现是根据图片路径前缀和图片路径拼接的完整地址。
那么肯定也是通过路径前缀 + 图片地址拼接出来的完整地址。关键就在图片路径前缀怎么确定的(肯定不是html页面的路径前缀哈)。
真相大白
通过浏览器访问构建后的lib库页面,查询这个__webpack_require_.p
关键字,发现是通过正则匹配相关内容后进行的赋值操作。
根据正则条件,在GitHub vue-cli源码中查找关键字,发现源码如下:
文件位置@vue\cli-service\lib\commands\build\setPublicPath.js
经过搜索,这段代码用于js文件在加载过程中,js读取到自身js的路径,赋值给__webpack_public_path__
。
__webpack_public_path__
是webpack官方提供的自由变量。
总结
所以真相就是js库文件在加载时,获取到了自身的js路径,赋值给自由变量。然后在图片资源路径生成时,路径读取的自由变量路径+图片资源路径自动拼接成了完整的图片地址。
后续我们在组件入口统一新增了这段赋值__webpack_public_path__
,验证后确实实现了在任何位置引用js组件,相对js组件文件位置的图片资源都正常加载。