如何获取vue单文件自身源码路径

2020-06-16 06:10:47易采站长站整理

方案 3 :loader + Custom Block

既然方案 2 不让在生产环境用,那就自己写 loader 去加上这个源码路径,这里采用了Custom Block。

这个方法是慢慢调试自定义的 loader 摸索出来的,先在 vue-loader 之前加自定义的 loader A,

去注入 Custom Block 代码,再在全局加入一个针对该 Custom Block 的 loader B。

这里将方案封装,在 chainWebpack 中调用即可:


/* vue.config.js */
const VueFilenameInjector = require('./path/to/vue-filename-injector')

module.exports = {
chainWebpack: config => {
VueFilenameInjector(config, {
propName: '__source' // default
})
}
}

源码参考:@d2-projects/d2-advance/tools/vue-filename-injector


.
└── vue-filename-injector
├── README.md
├── index.js
└── src
├── index.js
└── lib
├── config.js
├── injector.js
└── loader.js

vue-filename-injector/index.js:


const { blockName } = require('./lib/config.js')

// for chainWebpack
module.exports = function(config, options) {
// 注入
config.module
.rule('vue')
.use('vue-filename-injector')
.loader(require.resolve('./lib/injector.js'))
.options(options)
.after('vue-loader') // 不知为何 .before() 不是预期的结果,这里就绕了一下
.end()
// 解析
config.module
.rule('')
.resourceQuery(new RegExp(`blockType=${blockName}`))
.use('vue-filename-injector-loader')
.loader(require.resolve('./lib/loader.js'))
.end()
}

vue-filename-injector/lib/config.js:


const defaultPropName = '__source'
const blockName = 'vue-filename-injector'

module.exports = {
defaultPropName,
blockName
}

vue-filename-injector/lib/injector.js,源码部分来自 vue-loader:


const path = require('path')
const loaderUtils = require('loader-utils')

const { blockName, defaultPropName } = require('./config.js')

module.exports = function (content /*, map, meta */) {
const loaderContext = this

const {
rootContext,
resourcePath
} = loaderContext

const context = rootContext || process.cwd()
const options = loaderUtils.getOptions(loaderContext) || {}
const rawShortFilePath = path
.relative(context, resourcePath)
.replace(/^(..[/])+/, '')

const propName = options.propName || defaultPropName

content += `
<${blockName}>
export default function (Component) {
Component.options.${propName} = ${JSON.stringify(rawShortFilePath.replace(//g, '/'))}