When a module being loaded includes an export * from './path' which has not already been imported to the moduleCache, the loader fails with error
require("./path") failed. module not found in moduleCache
To Reproduce
To reproduce this behaviour import the following file tree within a .vue file
import * as x from './src/a.mjs'
This will result in the error
Error: require("PATH/B.mjs") failed. module not found in moduleCache
./src/a.mjs
export * from "./b.mjs"
export * from "./c.mjs"
export * from "./d.mjs"
./src/b.js
export function Wowza(name) {
alert(`WOWZA, ${name}`)
}
./src/c.mjs
export { }
./src/d.mjs
const d = { letter: "D" }
export { d }
Expected behaviour
I expect the loader to pre-empt the use of the export * from (b.mjs, c.mjs, d.mjs) modules exposed via './src/a.mjs' and resolve them to the moduleCache.
Additional context
For now I manually pre-assess the response in getFile(path) to regex match any export from './path'.
I then inject an import as x from './path' before the export.
This resolves the problem (I believe because vue3-sfc-loader then pre-empts the usage of that module and resolves it to the moduleCache before proceeding). This is the code I use in getFile.
async getFile(url) {
//console.log("getFile", url)
url = /\.(js|mjs|css|less|vue)$/.test(url) ? url : `${url}.${url.startsWith(window.location.origin) ? "vue" : "js"}`
const type = /.*?\.js|.mjs$/.test(url) ? ".mjs" : /.*?\.vue$/.test(url) ? '.vue' : /.*?\.css$/.test(url) ? '.css' : '.vue';
const fetched = await fetch(url);
if (!fetched.ok)
throw Object.assign(new Error(`${fetched.statusText} ${url}`), { fetched });
const getContentData = async asBinary => {
let content = await (asBinary ? fetched.arrayBuffer() : fetched.text());
// vue3-sfc-loader fails to import before attempting an [export * from "./path"] with ""
// prefixing any with an import statement to populate the moduleCache
if (!asBinary && content.includes("export * from")) {
const matches = content.matchAll(/export \* from (['"])([^'"]+)['"];?/g)
for (const match of matches) {
var module = options.pathResolve({ refPath: url, relPath: match[2] })
if (!options.moduleCache[module]) {
content = content.replace(match[0], `import * as vueLoaderExportSupport${match.index} from ${match[1]}${match[2]}${match[1]}\n${match[0]}\n`)
}
}
}
return content;
}
return { getContentData, type }
}
the above fix changes ./Src/a.mjs to the following, which stops the error occurring
import * as vueLoaderExportSupport1 from "./b.mjs"
export * from "./b.mjs"
import * as vueLoaderExportSupport2 from "./c.mjs"
export * from "./c.mjs"
import * as vueLoaderExportSupport3 from "./d.mjs"
export * from "./d.mjs"
When a module being loaded includes an export * from './path' which has not already been imported to the moduleCache, the loader fails with error
require("./path") failed. module not found in moduleCache
To Reproduce To reproduce this behaviour import the following file tree within a .vue file import * as x from './src/a.mjs'
This will result in the error Error: require("PATH/B.mjs") failed. module not found in moduleCache
Expected behaviour I expect the loader to pre-empt the use of the export * from (b.mjs, c.mjs, d.mjs) modules exposed via './src/a.mjs' and resolve them to the moduleCache.
Versions
Additional context For now I manually pre-assess the response in getFile(path) to regex match any export from './path'. I then inject an import as x from './path' before the export. This resolves the problem (I believe because vue3-sfc-loader then pre-empts the usage of that module and resolves it to the moduleCache before proceeding). This is the code I use in getFile.
the above fix changes ./Src/a.mjs to the following, which stops the error occurring