summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@matthewphillips.info> 2021-03-30 15:06:43 -0400
committerGravatar GitHub <noreply@github.com> 2021-03-30 15:06:43 -0400
commit4a732837cdd1ad5493a25ae58612e9b6a302c651 (patch)
tree724af4f76202d6615a6969cd2d2bd7e3723c3d4f
parent7334a550d8e042ae0dc59519149df2b3ad04f058 (diff)
downloadastro-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.cjs3
-rw-r--r--src/@types/compiler.ts3
-rw-r--r--src/compiler/codegen.ts25
-rw-r--r--src/compiler/index.ts9
-rw-r--r--src/frontend/render/renderer.ts2
-rw-r--r--src/runtime.ts2
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),
};