loadGuestComponent.js 1.5 KB

12345678910111213141516171819202122232425262728
  1. import fs from 'fs'
  2. import path from 'path'
  3. import { transformSync } from '@babel/core'
  4. import { parseComponent, compileTemplate } from 'vue/compiler-sfc'
  5. // 沿用项目的 Vue 2.7 SFC 测试方式,避免调用不匹配的旧 vue-jest 编译器。
  6. const cache = new Map()
  7. export function load(filename) {
  8. if (cache.has(filename)) return cache.get(filename)
  9. const parts = parseComponent(fs.readFileSync(filename, 'utf8'))
  10. const code = transformSync(parts.script.content, { babelrc: false, configFile: false, plugins: [require.resolve('@babel/plugin-transform-modules-commonjs')] }).code
  11. const module = { exports: {}}
  12. const localRequire = id => {
  13. if (id.startsWith('.') || id.startsWith('@/')) {
  14. let resolved = id.startsWith('.') ? path.resolve(path.dirname(filename), id) : path.resolve('src', id.slice(2))
  15. if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) resolved = path.join(resolved, 'index.js')
  16. else if (!path.extname(resolved)) resolved += '.js'
  17. return resolved.endsWith('.vue') ? load(resolved) : require(resolved)
  18. }
  19. return require(id)
  20. }
  21. new Function('require', 'module', 'exports', code)(localRequire, module, module.exports)
  22. const compiled = compileTemplate({ source: parts.template.content, filename })
  23. if (compiled.errors.length) throw new Error(compiled.errors.join('\n'))
  24. Object.assign(module.exports.default, new Function(compiled.code + ';return { render, staticRenderFns }')())
  25. cache.set(filename, module.exports.default)
  26. return module.exports.default
  27. }