diff --git a/package-lock.json b/package-lock.json index c7f9b0bb..bfa3a2fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "san-ssr", - "version": "1.3.8", + "version": "1.3.9", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/loaders/common-js.ts b/src/loaders/common-js.ts index 4e821b58..8277ac1e 100644 --- a/src/loaders/common-js.ts +++ b/src/loaders/common-js.ts @@ -30,6 +30,7 @@ export class CommonJS { public cache = new Map() constructor (modules: Modules = {}, readFile: FileLoader = defaultFileLoader) { + debug('CommonJS created') this.modules = modules if (typeof readFile === 'function') { this.readFileImpl = readFile @@ -40,10 +41,9 @@ export class CommonJS { require (filepath: string, specifier: string = filepath) { debug('global require called with', filepath) - if (!this.cache.has(filepath)) { + const [actualFilePath, fileContent] = this.readModuleContent(filepath, specifier) + if (!this.cache.has(actualFilePath)) { debug('cache miss, reading', filepath) - - const fileContent = this.readModuleContent(filepath, specifier) const mod = new Module(filepath, fileContent) const fn = new Function('module', 'exports', 'require', mod.content) // eslint-disable-line @@ -60,27 +60,30 @@ export class CommonJS { return require(path) }) - return mod.exports + this.cache.set(actualFilePath, mod.exports) } - return this.cache.get(filepath) + return this.cache.get(actualFilePath) } private readModuleContent (filepath: string, specifier: string) { if (this.modules[specifier] !== undefined) { - return this.modules[specifier] + return [specifier, this.modules[specifier]] } if (this.modules[filepath] !== undefined) { - return this.modules[filepath] + return [filepath, this.modules[filepath]] } - const fileContent = this.readFileImpl(filepath, specifier) || - this.readFileImpl(filepath + '.ts') || - this.readFileImpl(filepath + '.js') - - if (fileContent === undefined) { - throw new Error(`file ${filepath} not found`) + let fileContent + if ((fileContent = this.readFileImpl(filepath, specifier))) { + return [filepath, fileContent] + } + if ((fileContent = this.readFileImpl(filepath + '.ts', specifier))) { + return [filepath + '.ts', fileContent] + } + if ((fileContent = this.readFileImpl(filepath + '.js', specifier))) { + return [filepath + '.js', fileContent] } - return fileContent + throw new Error(`file ${filepath} not found`) } } diff --git a/src/models/san-project.ts b/src/models/san-project.ts index 5b3a86de..a6ac3d78 100644 --- a/src/models/san-project.ts +++ b/src/models/san-project.ts @@ -45,8 +45,7 @@ export class SanProject { } public parseSanApp (filepath: string) { - const parser = new SanAppParser(this.tsProject) - return parser.parseSanApp(resolve(filepath), this.modules) + return this.getParser().parseSanApp(resolve(filepath), this.modules) } private getOrCreateCompilerInstance (target: string | CompilerClass) { @@ -58,6 +57,10 @@ export class SanProject { return this.compilers.get(CompilerClass) } + private getParser () { + return new SanAppParser(this.tsProject) + } + private loadCompilerClass (target: string | CompilerClass) { if (typeof target === 'string') return loadCompilerClassByTarget(target) return target diff --git a/src/parsers/san-app-parser.ts b/src/parsers/san-app-parser.ts index 56d04553..00b446d2 100644 --- a/src/parsers/san-app-parser.ts +++ b/src/parsers/san-app-parser.ts @@ -14,13 +14,22 @@ import debugFactory from 'debug' const debug = debugFactory('component-parser') export class SanAppParser { + public project: Project private root: string private id: number = 0 - private cache: Map = new Map() - public project: Project + private cache: Map = new Map() + private projectFiles: Map = new Map() + private commonJS: CommonJS + private modules = {} constructor (project: Project) { + debug('SanAppParser created') this.project = project + this.commonJS = new CommonJS(this.modules, filepath => { + if (!this.projectFiles.has(filepath)) return undefined + const sourceFile = this.projectFiles.get(filepath) + return tsSourceFile2js(sourceFile.tsSourceFile, this.project.getCompilerOptions()) + }) } static createUsingTsconfig (tsConfigFilePath: string) { @@ -38,18 +47,17 @@ export class SanAppParser { ? SanSourceFile.createFromJSFilePath(entryFilePath) : this.parseSanSourceFile(this.project.getSourceFileOrThrow(entryFilePath)) - const projectFiles: Map = new Map() - projectFiles.set(entryFilePath, entrySourceFile) + this.projectFiles.set(entryFilePath, entrySourceFile) if (entrySourceFile.fileType === SourceFileType.ts) { const sourceFiles = getDependenciesRecursively(entrySourceFile.tsSourceFile) for (const [path, file] of sourceFiles) { - projectFiles.set(path, this.parseSanSourceFile(file)) + this.projectFiles.set(path, this.parseSanSourceFile(file)) } } - const entryClass = this.evaluateFile(entrySourceFile, projectFiles, modules) + const entryClass = this.evaluateFile(entrySourceFile, modules) const componentClasses = new ComponentClassFinder(entryClass).find() if (entrySourceFile.fileType === SourceFileType.js) { @@ -58,26 +66,23 @@ export class SanAppParser { componentClass.sanssrCid = i } } - return new SanApp(entrySourceFile, projectFiles, componentClasses) + return new SanApp(entrySourceFile, this.projectFiles, componentClasses) } - private evaluateFile (sourceFile: SanSourceFile, projectFiles: Map, modules: Modules) { + private evaluateFile (sourceFile: SanSourceFile, modules: Modules) { if (sourceFile.fileType === SourceFileType.js) { - return new CommonJS().require(sourceFile.getFilePath()) + return this.commonJS.require(sourceFile.getFilePath()) } - const commonJS = new CommonJS(modules, filepath => { - if (!projectFiles.has(filepath)) return undefined - const sourceFile = projectFiles.get(filepath) - return tsSourceFile2js(sourceFile.tsSourceFile, this.project.getCompilerOptions()) - }) - return commonJS.require(sourceFile.getFilePath()).default + Object.assign(this.modules, modules) + return this.commonJS.require(sourceFile.getFilePath()).default } private parseSanSourceFile (sourceFile: SourceFile) { - if (!this.cache.has(sourceFile)) { - this.cache.set(sourceFile, this.doParseSanSourceFile(sourceFile)) + const filePath = sourceFile.getFilePath() + if (!this.cache.has(filePath)) { + this.cache.set(filePath, this.doParseSanSourceFile(sourceFile)) } - return this.cache.get(sourceFile) + return this.cache.get(filePath) } private doParseSanSourceFile (sourceFile: SourceFile) {