Skip to content

Commit d7fb4b6

Browse files
feat: support external esm module scripts
1 parent 6b57249 commit d7fb4b6

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

sandpack-client/src/clients/runtime/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
SandpackErrorMessage,
1212
SandpackLogLevel,
1313
SandpackMessageConsoleMethods,
14+
ExternalScriptResource
1415
} from "../..";
1516

1617
export type SandpackRuntimeMessage = BaseSandpackMessage &
@@ -66,7 +67,7 @@ export type SandpackRuntimeMessage = BaseSandpackMessage &
6667
version: number;
6768
isInitializationCompile?: boolean;
6869
modules: Modules;
69-
externalResources: string[];
70+
externalResources?: Array<string | ExternalScriptResource>;
7071
hasFileResolver: boolean;
7172
disableDependencyPreprocessing?: boolean;
7273
template?: string | ITemplate;

sandpack-client/src/clients/static/index.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { PreviewController } from "static-browser-server";
55

66
import type {
77
ClientOptions,
8+
ExternalScriptResource,
89
ListenerFunction,
910
SandboxSetup,
1011
UnsubscribeFunction,
@@ -132,26 +133,37 @@ export class SandpackStatic extends SandpackClient {
132133
): FileContent {
133134
const tagsToInsert = externalResources
134135
.map((resource) => {
135-
const match = resource.match(/\.([^.]*)$/);
136-
const fileType = match?.[1];
137-
138-
if (fileType === "css" || resource.includes("fonts.googleapis")) {
139-
return `<link rel="stylesheet" href="${resource}">`;
140-
}
141-
142-
if (fileType === "js") {
143-
return `<script src="${resource}"></script>`;
136+
if (this.isScriptResource(resource)) {
137+
return `<script type="${resource.type}" src="${resource.src}"></script>`;
138+
} else {
139+
const match = resource.match(/\.([^.]*)$/);
140+
const fileType = match?.[1];
141+
142+
if (fileType === "css" || resource.includes("fonts.googleapis")) {
143+
return `<link rel="stylesheet" href="${resource}">`;
144+
}
145+
146+
if (fileType === "js") {
147+
return `<script src="${resource}"></script>`;
148+
}
149+
150+
throw new Error(
151+
`Unable to determine file type for external resource: ${resource}`
152+
);
144153
}
145-
146-
throw new Error(
147-
`Unable to determine file type for external resource: ${resource}`
148-
);
149154
})
150155
.join("\n");
151156

152157
return this.injectContentIntoHead(content, tagsToInsert);
153158
}
154159

160+
private isScriptResource(resource: unknown): resource is ExternalScriptResource {
161+
return typeof resource === 'object'
162+
&& resource !== null
163+
&& 'type' in resource
164+
&& 'src' in resource;
165+
}
166+
155167
private injectScriptIntoHead(
156168
content: FileContent,
157169
opts: {

sandpack-client/src/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export interface ClientOptions {
55
/**
66
* Paths to external resources
77
*/
8-
externalResources?: string[];
8+
externalResources?: Array<string | ExternalScriptResource>;
99
/**
1010
* Location of the bundler.
1111
*/
@@ -72,6 +72,11 @@ export interface ClientOptions {
7272
teamId?: string;
7373
}
7474

75+
export interface ExternalScriptResource {
76+
type: "module" | "importmap" | undefined;
77+
src: string;
78+
}
79+
7580
export interface SandboxSetup {
7681
files: SandpackBundlerFiles;
7782
dependencies?: Dependencies;

sandpack-react/src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
UnsubscribeFunction,
1313
SandpackLogLevel,
1414
NpmRegistry,
15+
ExternalScriptResource
1516
} from "@codesandbox/sandpack-client";
1617
import type React from "react";
1718

@@ -171,7 +172,8 @@ export interface SandpackOptions {
171172
startRoute?: string;
172173
skipEval?: boolean;
173174
fileResolver?: FileResolver;
174-
externalResources?: string[];
175+
176+
externalResources?: Array<string | ExternalScriptResource>;
175177
}
176178

177179
/**
@@ -460,7 +462,7 @@ export interface SandpackInternalOptions<
460462
startRoute?: string;
461463
skipEval?: boolean;
462464
fileResolver?: FileResolver;
463-
externalResources?: string[];
465+
externalResources?: Array<string | ExternalScriptResource>;
464466
classes?: Record<string, string>;
465467
}
466468

website/docs/src/pages/advanced-usage/client.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ The `getCodeSandboxURL` method creates a sandbox from the current files and retu
291291
/**
292292
* Paths to external resources
293293
*/
294-
externalResources?: string[];
294+
externalResources?: Array<string | ExternalScriptResource>;
295295
/**
296296
* Location of the bundler. Defaults to `${version}-sandpack.codesandbox.io`
297297
*/

0 commit comments

Comments
 (0)