Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multiple cdn v2 #10189

Merged
merged 36 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fa3454a
feat: add multiple cdn
peng Feb 21, 2024
12ed2dc
add multiple cdn test
peng Feb 21, 2024
327d8c2
assetsPrefix not empty string
peng Feb 22, 2024
3c00925
add changeset
peng Feb 22, 2024
0ef27ca
simplify code
peng Feb 23, 2024
47b3d5f
change docs
peng Feb 29, 2024
3a1dcdb
replace getFileExtension with node path.extname
peng Feb 29, 2024
acd1ec9
Adapt node extname
peng Mar 1, 2024
0600b34
Merge branch 'main' into add-multiple-cdn-v2
peng Mar 1, 2024
99f53f7
multiple image test
peng Mar 1, 2024
ecd9414
Merge branch 'main' into add-multiple-cdn-v2
peng Mar 4, 2024
7e6467d
wip space
peng Mar 4, 2024
30b2cd7
update docs
peng Mar 4, 2024
3f769fa
update docs, assetsPrefix type
peng Mar 4, 2024
91ea28e
update docs
peng Mar 4, 2024
de65e0a
update docs
peng Mar 4, 2024
eef88df
chore: update types and rename to `fallback`
ematipico Mar 5, 2024
17cebd0
enhance changelog
ematipico Mar 5, 2024
e352287
Merge remote-tracking branch 'origin/main' into add-multiple-cdn-v2
ematipico Mar 5, 2024
2b4cd7d
change docs
peng Mar 5, 2024
d3e755e
update change defaultAeestsPrefix to fallback key test
peng Mar 5, 2024
a7f5809
Merge branch 'main' into add-multiple-cdn-v2
peng Mar 6, 2024
b101631
Merge remote-tracking branch 'origin/main' into add-multiple-cdn-v2
ematipico Mar 6, 2024
b95b782
move utility to a new to avoid importing `node:path` inside vite plugins
ematipico Mar 6, 2024
eb5eec9
Update packages/astro/src/@types/astro.ts
ematipico Mar 7, 2024
b36026e
Apply suggestions from code review
ematipico Mar 7, 2024
7e773a9
chore: address Bjorn's comments
ematipico Mar 7, 2024
8ed6f4f
kill the variable
ematipico Mar 7, 2024
dcf45fe
kill the variable /2
ematipico Mar 7, 2024
1e4faae
Fix CI fail
bluwy Mar 7, 2024
112d50b
Apply suggestions from code review
Princesseuh Mar 7, 2024
45674bc
uniform code sample
sarah11918 Mar 7, 2024
a7e1699
add `.` string for fit getAssetsPrefix
peng Mar 8, 2024
fc425bc
Fix extension function
bluwy Mar 8, 2024
cb4ca92
Merge branch 'main' into add-multiple-cdn-v2
ematipico Mar 8, 2024
2371fb7
Merge branch 'main' into add-multiple-cdn-v2
ematipico Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/fluffy-readers-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@astrojs/internal-helpers": minor
"astro": minor
---

Adds the option to pass an object to `build.assetsPrefix`. This allows for the use of multiple CDN prefixes based on the target filetype.
Princesseuh marked this conversation as resolved.
Show resolved Hide resolved
31 changes: 27 additions & 4 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type * as babel from '@babel/core';
import type * as rollup from 'rollup';
import type * as vite from 'vite';
import type { RemotePattern } from '../assets/utils/remotePattern.js';
import type { SerializedSSRManifest } from '../core/app/types.js';
import type { SerializedSSRManifest, AssetsPrefix } from '../core/app/types.js';
import type { PageBuildData } from '../core/build/types.js';
import type { AstroConfigType } from '../core/config/index.js';
import type { AstroTimer } from '../core/config/timer.js';
Expand Down Expand Up @@ -67,7 +67,7 @@ export type {
UnresolvedImageTransform,
} from '../assets/types.js';
export type { RemotePattern } from '../assets/utils/remotePattern.js';
export type { SSRManifest } from '../core/app/types.js';
export type { SSRManifest, AssetsPrefix } from '../core/app/types.js';
export type {
AstroCookieGetOptions,
AstroCookieSetOptions,
Expand Down Expand Up @@ -881,11 +881,13 @@ export interface AstroUserConfig {
/**
* @docs
* @name build.assetsPrefix
* @type {string}
* @type {string | Record<string, string>}
ematipico marked this conversation as resolved.
Show resolved Hide resolved
* @default `undefined`
* @version 2.2.0
* @description
* Specifies the prefix for Astro-generated asset links. This can be used if assets are served from a different domain than the current site.
ematipico marked this conversation as resolved.
Show resolved Hide resolved
*
* If this value is a `string`,
*
* For example, if this is set to `https://cdn.example.com`, assets will be fetched from `https://cdn.example.com/_astro/...` (regardless of the `base` option).
* You would need to upload the files in `./dist/_astro/` to `https://cdn.example.com/_astro/` to serve the assets.
Expand All @@ -899,8 +901,29 @@ export interface AstroUserConfig {
* }
* }
* ```
*
* If this value is a `Record<string, string>`,
*
* Applicable to multiple CDN scenarios. If you static file use different CDN, you can configure it like the example below.
*
* For example, if static file is js file, assets prefix use `https://js.cdn.example.com`. If static file is css file, assets prefix use `https://css.cdn.example.com`. Other assets prefix use `https://cdn.example.com`.
*
* ```js
* {
* build: {
* assetsPrefix: {
* 'js': 'https://js.cdn.example.com',
* 'css': 'https://js.cdn.example.com',
* 'defaultAssetsPrefix': 'https://cdn.example.com'
* }
* }
* }
* ```
*
* Object key is file extension, value is CDN assets prefix path. `defaultAssetsPrefix` is default assets prefix cdn value set. You can set the default values of other files by setting the value of `defaultAssetsPrefix`. If `defaultAssetsPrefix` is not set, when the file extension is not found in the `assetsPrefix` object, it will be set to the empty string `''` by default.
*
*/
assetsPrefix?: string;
assetsPrefix?: AssetsPrefix;
ematipico marked this conversation as resolved.
Show resolved Hide resolved
/**
* @docs
* @name build.serverEntry
Expand Down
13 changes: 13 additions & 0 deletions packages/astro/src/assets/utils/transformToPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { removeQueryString } from '../../core/path.js';
import { shorthash } from '../../runtime/server/shorthash.js';
import type { ImageTransform } from '../types.js';
import { isESMImportedImage } from './imageKind.js';
import type { AssetsPrefix } from '../../@types/astro.js';

export function propsToFilename(transform: ImageTransform, hash: string) {
let filename = removeQueryString(
Expand Down Expand Up @@ -33,3 +34,15 @@ export function hashTransform(
);
return shorthash(deterministicString(hashFields));
}

export function getAssetsPrefix(fileType: string, assetsPrefix?: AssetsPrefix):string {
if (!assetsPrefix) return '';
if (typeof assetsPrefix === 'string') return assetsPrefix;
fileType = fileType[0] === '.' ? fileType.slice(1) : fileType;
bluwy marked this conversation as resolved.
Show resolved Hide resolved
if (assetsPrefix[fileType]) {
return assetsPrefix[fileType];
} else if (assetsPrefix.defaultAssetsPrefix) {
return assetsPrefix.defaultAssetsPrefix;
}
return '';
}
18 changes: 11 additions & 7 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import MagicString from 'magic-string';
import type * as vite from 'vite';
import { normalizePath } from 'vite';
import { extname } from 'node:path';
import type { AstroPluginOptions, ImageTransform } from '../@types/astro.js';
import { extendManualChunks } from '../core/build/plugins/util.js';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
Expand All @@ -15,7 +16,7 @@ import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from './co
import { emitESMImage } from './utils/emitAsset.js';
import { isESMImportedImage } from './utils/imageKind.js';
import { getProxyCode } from './utils/proxy.js';
import { hashTransform, propsToFilename } from './utils/transformToPath.js';
import { getAssetsPrefix, hashTransform, propsToFilename } from './utils/transformToPath.js';

const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;

Expand Down Expand Up @@ -95,9 +96,10 @@ export default function assets({
}

// Rollup will copy the file to the output directory, this refer to this final path, not to the original path
const finalOriginalImagePath = (
isESMImportedImage(options.src) ? options.src.src : options.src
).replace(settings.config.build.assetsPrefix || '', '');
const ESMImportedImageSrc = isESMImportedImage(options.src) ? options.src.src : options.src;
const fileExtension = extname(ESMImportedImageSrc);
const pf = getAssetsPrefix(fileExtension, settings.config.build.assetsPrefix);
bluwy marked this conversation as resolved.
Show resolved Hide resolved
const finalOriginalImagePath = ESMImportedImageSrc.replace(pf, '');

const hash = hashTransform(
options,
Expand Down Expand Up @@ -132,7 +134,7 @@ export default function assets({
// The paths here are used for URLs, so we need to make sure they have the proper format for an URL
// (leading slash, prefixed with the base / assets prefix, encoded, etc)
if (settings.config.build.assetsPrefix) {
return encodeURI(joinPaths(settings.config.build.assetsPrefix, finalFilePath));
return encodeURI(joinPaths(pf, finalFilePath));
} else {
return encodeURI(prependForwardSlash(joinPaths(settings.config.base, finalFilePath)));
}
Expand All @@ -149,8 +151,10 @@ export default function assets({
const [full, hash, postfix = ''] = match;

const file = this.getFileName(hash);
const prefix = settings.config.build.assetsPrefix
? appendForwardSlash(settings.config.build.assetsPrefix)
const fileExtension = extname(file)
const pf = getAssetsPrefix(fileExtension, settings.config.build.assetsPrefix)
const prefix = pf
? appendForwardSlash(pf)
: resolvedConfig.base;
const outputFilepath = prefix + normalizePath(file + postfix);

Expand Down
8 changes: 6 additions & 2 deletions packages/astro/src/content/vite-plugin-content-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
STYLES_PLACEHOLDER,
} from './consts.js';
import { hasContentFlag } from './utils.js';
import { getAssetsPrefix } from '../assets/utils/transformToPath.js';

export function astroContentAssetPropagationPlugin({
mode,
Expand Down Expand Up @@ -141,8 +142,11 @@ export function astroConfigBuildPlugin(
'build:post': ({ ssrOutputs, clientOutputs, mutate }) => {
const outputs = ssrOutputs.flatMap((o) => o.output);
const prependBase = (src: string) => {
if (options.settings.config.build.assetsPrefix) {
return joinPaths(options.settings.config.build.assetsPrefix, src);
const { assetsPrefix } = options.settings.config.build
if (assetsPrefix) {
const fileExtension = extname(src)
const pf = getAssetsPrefix(fileExtension, assetsPrefix)
return joinPaths(pf, src);
} else {
return prependForwardSlash(joinPaths(options.settings.config.base, src));
}
Expand Down
4 changes: 3 additions & 1 deletion packages/astro/src/core/app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export type SerializedRouteInfo = Omit<RouteInfo, 'routeData'> & {

export type ImportComponentInstance = () => Promise<SinglePageBuiltModule>;

export type AssetsPrefix = string | Record<string, string>

export type SSRManifest = {
adapterName: string;
routes: RouteInfo[];
Expand All @@ -43,7 +45,7 @@ export type SSRManifest = {
trailingSlash: 'always' | 'never' | 'ignore';
buildFormat: 'file' | 'directory' | 'preserve';
compressHTML: boolean;
assetsPrefix?: string;
assetsPrefix?: AssetsPrefix;
renderers: SSRLoadedRenderer[];
/**
* Map of directive name (e.g. `load`) to the directive script code
Expand Down
6 changes: 5 additions & 1 deletion packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { fileURLToPath } from 'node:url';
import { extname } from 'node:path';
import glob from 'fast-glob';
import type { OutputChunk } from 'rollup';
import { type Plugin as VitePlugin } from 'vite';
Expand All @@ -18,6 +19,7 @@ import { getOutFile, getOutFolder } from '../common.js';
import { type BuildInternals, cssOrder, mergeInlineCss } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types.js';
import { getAssetsPrefix } from '../../../assets/utils/transformToPath.js';

const manifestReplace = '@@ASTRO_MANIFEST_REPLACE@@';
const replaceExp = new RegExp(`['"]${manifestReplace}['"]`, 'g');
Expand Down Expand Up @@ -163,7 +165,9 @@ function buildManifest(

const prefixAssetPath = (pth: string) => {
if (settings.config.build.assetsPrefix) {
return joinPaths(settings.config.build.assetsPrefix, pth);
const fileType = extname(pth)
const pf = getAssetsPrefix(fileType, settings.config.build.assetsPrefix)
return joinPaths(pf, pth);
} else {
return prependForwardSlash(joinPaths(settings.config.base, pth));
}
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const AstroConfigSchema = z.object({
.default(ASTRO_CONFIG_DEFAULTS.build.server)
.transform((val) => new URL(val)),
assets: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.assets),
assetsPrefix: z.string().optional(),
assetsPrefix: z.string().optional().or(z.record(z.string()).optional()),
ematipico marked this conversation as resolved.
Show resolved Hide resolved
serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry),
redirects: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.redirects),
inlineStylesheets: z
Expand Down Expand Up @@ -508,7 +508,7 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) {
.default(ASTRO_CONFIG_DEFAULTS.build.server)
.transform((val) => resolveDirAsUrl(val, fileProtocolRoot)),
assets: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.assets),
assetsPrefix: z.string().optional(),
assetsPrefix: z.string().optional().or(z.record(z.string()).optional()),
serverEntry: z.string().optional().default(ASTRO_CONFIG_DEFAULTS.build.serverEntry),
redirects: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.redirects),
inlineStylesheets: z
Expand Down
10 changes: 6 additions & 4 deletions packages/astro/src/core/create-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import type { Logger } from './logger/core.js';
import { createViteLogger } from './logger/vite.js';
import { vitePluginMiddleware } from './middleware/vite-plugin.js';
import { joinPaths } from './path.js';
import { getAssetsPrefix } from '../assets/utils/transformToPath.js';
import { isObject } from './util.js';

interface CreateViteOptions {
settings: AstroSettings;
Expand Down Expand Up @@ -214,9 +216,9 @@ export async function createVite(
const assetsPrefix = settings.config.build.assetsPrefix;
if (assetsPrefix) {
commonConfig.experimental = {
renderBuiltUrl(filename, { type }) {
renderBuiltUrl(filename, { type, hostType }) {
ematipico marked this conversation as resolved.
Show resolved Hide resolved
if (type === 'asset') {
return joinPaths(assetsPrefix, filename);
return joinPaths(getAssetsPrefix(hostType, assetsPrefix), filename);
}
},
};
Expand Down Expand Up @@ -318,6 +320,6 @@ function isCommonNotAstro(dep: string): boolean {
);
}

function stringifyForDefine(value: string | undefined): string {
return typeof value === 'string' ? JSON.stringify(value) : 'undefined';
function stringifyForDefine(value: string | undefined | object): string {
ematipico marked this conversation as resolved.
Show resolved Hide resolved
return (typeof value === "string" || isObject(value)) ? JSON.stringify(value) : "undefined";
}
22 changes: 13 additions & 9 deletions packages/astro/src/core/render/ssr-element.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import type { SSRElement } from '../../@types/astro.js';
import { extname } from 'node:path';
import type { SSRElement, AssetsPrefix } from '../../@types/astro.js';
import { joinPaths, prependForwardSlash, slash } from '../../core/path.js';
import type { StylesheetAsset } from '../app/types.js';
import { getAssetsPrefix } from '../../assets/utils/transformToPath.js';

export function createAssetLink(href: string, base?: string, assetsPrefix?: string): string {
export function createAssetLink(href: string, base?: string, assetsPrefix?: AssetsPrefix): string {
if (assetsPrefix) {
return joinPaths(assetsPrefix, slash(href));
const fileType = extname(href)
const pf = getAssetsPrefix(fileType, assetsPrefix)
return joinPaths(pf, slash(href));
} else if (base) {
return prependForwardSlash(joinPaths(base, slash(href)));
} else {
Expand All @@ -15,7 +19,7 @@ export function createAssetLink(href: string, base?: string, assetsPrefix?: stri
export function createStylesheetElement(
stylesheet: StylesheetAsset,
base?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): SSRElement {
if (stylesheet.type === 'inline') {
return {
Expand All @@ -36,15 +40,15 @@ export function createStylesheetElement(
export function createStylesheetElementSet(
stylesheets: StylesheetAsset[],
base?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): Set<SSRElement> {
return new Set(stylesheets.map((s) => createStylesheetElement(s, base, assetsPrefix)));
}

export function createModuleScriptElement(
script: { type: 'inline' | 'external'; value: string },
base?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): SSRElement {
if (script.type === 'external') {
return createModuleScriptElementWithSrc(script.value, base, assetsPrefix);
Expand All @@ -61,7 +65,7 @@ export function createModuleScriptElement(
export function createModuleScriptElementWithSrc(
src: string,
base?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): SSRElement {
return {
props: {
Expand All @@ -75,7 +79,7 @@ export function createModuleScriptElementWithSrc(
export function createModuleScriptElementWithSrcSet(
srces: string[],
site?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): Set<SSRElement> {
return new Set<SSRElement>(
srces.map((src) => createModuleScriptElementWithSrc(src, site, assetsPrefix))
Expand All @@ -85,7 +89,7 @@ export function createModuleScriptElementWithSrcSet(
export function createModuleScriptsSet(
scripts: { type: 'inline' | 'external'; value: string }[],
base?: string,
assetsPrefix?: string
assetsPrefix?: AssetsPrefix
): Set<SSRElement> {
return new Set<SSRElement>(
scripts.map((script) => createModuleScriptElement(script, base, assetsPrefix))
Expand Down
Loading
Loading