diff options
author | 2021-03-30 15:06:43 -0400 | |
---|---|---|
committer | 2021-03-30 15:06:43 -0400 | |
commit | 4a732837cdd1ad5493a25ae58612e9b6a302c651 (patch) | |
tree | 724af4f76202d6615a6969cd2d2bd7e3723c3d4f | |
parent | 7334a550d8e042ae0dc59519149df2b3ad04f058 (diff) | |
download | astro-4a732837cdd1ad5493a25ae58612e9b6a302c651.tar.gz astro-4a732837cdd1ad5493a25ae58612e9b6a302c651.tar.zst astro-4a732837cdd1ad5493a25ae58612e9b6a302c651.zip |
Resolve component URLs during compilation (#40)
Previously dynamic component URLs were being resolved client-side in a weird way that only worked during dev. This change makes them handle during compilation, so it works in both (and improves readability of the dynamic import output).
-rw-r--r-- | snowpack-plugin.cjs | 3 | ||||
-rw-r--r-- | src/@types/compiler.ts | 3 | ||||
-rw-r--r-- | src/compiler/codegen.ts | 25 | ||||
-rw-r--r-- | src/compiler/index.ts | 9 | ||||
-rw-r--r-- | src/frontend/render/renderer.ts | 2 | ||||
-rw-r--r-- | src/runtime.ts | 2 |
6 files changed, 28 insertions, 16 deletions
diff --git a/snowpack-plugin.cjs b/snowpack-plugin.cjs index f4f2edb81..dcb714ea6 100644 --- a/snowpack-plugin.cjs +++ b/snowpack-plugin.cjs @@ -3,7 +3,7 @@ const { readFile } = require('fs').promises; // Snowpack plugins must be CommonJS :( const transformPromise = import('./lib/compiler/index.js'); -module.exports = function (snowpackConfig, { resolve, extensions } = {}) { +module.exports = function (snowpackConfig, { resolve, extensions, astroConfig } = {}) { return { name: 'snowpack-astro', knownEntrypoints: ['deepmerge'], @@ -16,6 +16,7 @@ module.exports = function (snowpackConfig, { resolve, extensions } = {}) { const projectRoot = snowpackConfig.root; const contents = await readFile(filePath, 'utf-8'); const compileOptions = { + astroConfig, resolve, extensions, }; diff --git a/src/@types/compiler.ts b/src/@types/compiler.ts index 916be22cb..916242c51 100644 --- a/src/@types/compiler.ts +++ b/src/@types/compiler.ts @@ -1,8 +1,9 @@ import type { LogOptions } from '../logger'; -import type { ValidExtensionPlugins } from './astro'; +import type { AstroConfig, ValidExtensionPlugins } from './astro'; export interface CompileOptions { logging: LogOptions; resolve: (p: string) => Promise<string>; + astroConfig: AstroConfig; extensions?: Record<string, ValidExtensionPlugins>; } diff --git a/src/compiler/codegen.ts b/src/compiler/codegen.ts index febb0a514..add38baad 100644 --- a/src/compiler/codegen.ts +++ b/src/compiler/codegen.ts @@ -1,5 +1,5 @@ import type { CompileOptions } from '../@types/compiler'; -import type { ValidExtensionPlugins } from '../@types/astro'; +import type { AstroConfig, ValidExtensionPlugins } from '../@types/astro'; import type { Ast, TemplateNode } from '../parser/interfaces'; import type { JsxItem, TransformResult } from '../@types/astro'; @@ -111,14 +111,25 @@ const defaultExtensions: Readonly<Record<string, ValidExtensionPlugins>> = { type DynamicImportMap = Map<'vue' | 'react' | 'react-dom' | 'preact', string>; -function getComponentWrapper(_name: string, { type, plugin, url }: ComponentInfo, dynamicImports: DynamicImportMap) { +interface GetComponentWrapperOptions { + filename: string; + astroConfig: AstroConfig; + dynamicImports: DynamicImportMap; +} +function getComponentWrapper(_name: string, { type, plugin, url }: ComponentInfo, opts: GetComponentWrapperOptions) { + const { astroConfig, dynamicImports, filename } = opts; + const { astroRoot } = astroConfig; const [name, kind] = _name.split(':'); + const currFileUrl = new URL(`file://${filename}`); if (!plugin) { throw new Error(`No supported plugin found for extension ${type}`); } - const getComponentUrl = (ext = '.js') => `new URL(${JSON.stringify(url.replace(/\.[^.]+$/, ext))}, \`http://TEST\${import.meta.url\}\`).pathname.replace(/^\\/\\//, '/_astro/')`; + const getComponentUrl = (ext = '.js') => { + const outUrl = new URL(url, currFileUrl); + return '/_astro/' + path.posix.relative(astroRoot.pathname, outUrl.pathname).replace(/\.[^.]+$/, ext); + }; switch (plugin) { case 'astro': { @@ -242,8 +253,8 @@ async function acquireDynamicComponentImports(plugins: Set<ValidExtensionPlugins return importMap; } -export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Promise<TransformResult> { - const { extensions = defaultExtensions } = compileOptions; +export async function codegen(ast: Ast, { compileOptions, filename }: CodeGenOptions): Promise<TransformResult> { + const { extensions = defaultExtensions, astroConfig } = compileOptions; await eslexer.init; const componentImports: ImportDeclaration[] = []; @@ -343,7 +354,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro if (!components[componentName]) { throw new Error(`Unknown Component: ${componentName}`); } - const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], dynamicImports); + const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], {astroConfig, dynamicImports, filename}); if (wrapperImport) { importExportStatements.add(wrapperImport); } @@ -395,7 +406,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro if (!componentImportData) { throw new Error(`Unknown Component: ${componentName}`); } - const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], dynamicImports); + const { wrapper, wrapperImport } = getComponentWrapper(name, components[componentName], {astroConfig, dynamicImports, filename}); if (wrapperImport) { importExportStatements.add(wrapperImport); } diff --git a/src/compiler/index.ts b/src/compiler/index.ts index 945d9bfc5..8104ef4b4 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -1,4 +1,5 @@ import type { LogOptions } from '../logger.js'; +import type { AstroConfig } from '../@types/astro'; import path from 'path'; import micromark from 'micromark'; @@ -14,15 +15,11 @@ import { optimize } from './optimize/index.js'; import { codegen } from './codegen.js'; interface CompileOptions { + astroConfig: AstroConfig; logging: LogOptions; resolve: (p: string) => Promise<string>; } -const defaultCompileOptions: CompileOptions = { - logging: defaultLogOptions, - resolve: (p: string) => Promise.resolve(p), -}; - function internalImport(internalPath: string) { return `/_astro_internal/${internalPath}`; } @@ -107,7 +104,7 @@ async function transformFromSource( export async function compileComponent( source: string, - { compileOptions = defaultCompileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string } + { compileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string } ): Promise<CompileResult> { const sourceJsx = await transformFromSource(source, { compileOptions, filename, projectRoot }); const isPage = path.extname(filename) === '.md' || sourceJsx.items.some((item) => item.name === 'html'); diff --git a/src/frontend/render/renderer.ts b/src/frontend/render/renderer.ts index ceb460e40..d7afc0558 100644 --- a/src/frontend/render/renderer.ts +++ b/src/frontend/render/renderer.ts @@ -23,7 +23,7 @@ export function createRenderer(renderer: Renderer) { return [...acc, `import("${context.frameworkUrls[lib as any]}")`]; }, []) .join(','); - return `const [{${context.componentExport}: Component}, ${values}] = await Promise.all([import(${context.componentUrl})${renderer.imports ? ', ' + libs : ''}]);`; + return `const [{${context.componentExport}: Component}, ${values}] = await Promise.all([import("${context.componentUrl}")${renderer.imports ? ', ' + libs : ''}]);`; }; const serializeProps = (props: Record<string, any>) => JSON.stringify(props); const createContext = () => { diff --git a/src/runtime.ts b/src/runtime.ts index 3b2cffefc..42024eff4 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -126,7 +126,9 @@ export async function createRuntime(astroConfig: AstroConfig, { logging }: Runti const astroPlugOptions: { resolve?: (s: string) => Promise<string>; extensions?: Record<string, string>; + astroConfig: AstroConfig; } = { + astroConfig, extensions, resolve: async (pkgName: string) => snowpack.getUrlForPackage(pkgName), }; |