diff --git a/src/index.ts b/src/index.ts index 890dc1cb3..8717e91e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,6 +34,7 @@ export interface VueLoaderOptions { transformAssetUrls?: SFCTemplateCompileOptions['transformAssetUrls'] compiler?: TemplateCompiler | string compilerOptions?: CompilerOptions + useAbsolutePath?: boolean /** * TODO remove in 3.4 * @deprecated @@ -314,10 +315,8 @@ export default function loader( if (!isProduction) { // Expose the file's full path in development, so that it can be opened // from the devtools. - propsToAttach.push([ - `__file`, - JSON.stringify(rawShortFilePath.replace(/\\/g, '/')), - ]) + const base = options.useAbsolutePath ? filename : rawShortFilePath + propsToAttach.push([`__file`, JSON.stringify(base.replace(/\\/g, '/'))]) } else if (options.exposeFilename) { // Libraries can opt-in to expose their components' filenames in production builds. // For security reasons, only expose the file's basename in production. diff --git a/src/pluginWebpack5.ts b/src/pluginWebpack5.ts index b2286975e..f5eee2e35 100644 --- a/src/pluginWebpack5.ts +++ b/src/pluginWebpack5.ts @@ -13,8 +13,7 @@ const NormalModule = require('webpack/lib/NormalModule') const BasicEffectRulePlugin = require('webpack/lib/rules/BasicEffectRulePlugin') const BasicMatcherRulePlugin = require('webpack/lib/rules/BasicMatcherRulePlugin') const UseEffectRulePlugin = require('webpack/lib/rules/UseEffectRulePlugin') -const RuleSetCompiler = - require('webpack/lib/rules/RuleSetCompiler') as RuleSetCompiler +const RuleSetCompiler = require('webpack/lib/rules/RuleSetCompiler') as RuleSetCompiler let objectMatcherRulePlugins = [] try { diff --git a/test/advanced.spec.ts b/test/advanced.spec.ts index 25cd62265..a4842ce59 100644 --- a/test/advanced.spec.ts +++ b/test/advanced.spec.ts @@ -8,6 +8,7 @@ import { genId, DEFAULT_VUE_USE, } from './utils' +import path from 'path' const MiniCssExtractPlugin = require('mini-css-extract-plugin') @@ -55,7 +56,6 @@ test('no __file in production when exposeFilename disabled', async () => { expect(componentModule.__file).toBe(undefined) }) - test('expose file basename as __file in production when exposeFilename enabled', async () => { const { componentModule } = await mockBundleAndRun({ mode: 'production', @@ -67,6 +67,35 @@ test('expose file basename as __file in production when exposeFilename enabled', expect(componentModule.__file).toBe('basic.vue') }) +test('use absolute path', async () => { + const { componentModule } = await mockBundleAndRun({ + mode: 'development', + entry: 'basic.vue', + vue: { + useAbsolutePath: true, + }, + }) + + expect(componentModule.__file).toBe( + path.join(__dirname, 'fixtures/basic.vue') + ) +}) + +test('use absolute path and expose filename in production', async () => { + const { componentModule } = await mockBundleAndRun({ + mode: 'development', + entry: 'basic.vue', + vue: { + useAbsolutePath: true, + exposeFilename: true, + }, + }) + + expect(componentModule.__file).toBe( + path.join(__dirname, 'fixtures/basic.vue') + ) +}) + test.skip('source map', async () => { const { code } = await bundle({ entry: 'basic.vue',