Skip to content

Commit

Permalink
allow publicAssetURL to differ from rootURL
Browse files Browse the repository at this point in the history
This serves as a replacement for the classic `prepend` in broccoli-asset-rev.
  • Loading branch information
ef4 committed Dec 9, 2020
1 parent 68e75a6 commit b4106a7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
2 changes: 1 addition & 1 deletion packages/compat/src/default-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function defaultVariants(emberApp: any): Variant[] {
} else {
variants.push({
name: 'dev',
runtime: 'all',
runtime: hasFastboot(emberApp) ? 'all' : 'browser',
optimizeForProduction: false,
});
}
Expand Down
26 changes: 19 additions & 7 deletions packages/webpack/src/ember-webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ interface AppInfo {
templateCompiler: AppMeta['template-compiler'];
babel: AppMeta['babel'];
rootURL: AppMeta['root-url'];
publicAssetURL: string;
resolvableExtensions: AppMeta['resolvable-extensions'];
}

Expand All @@ -62,6 +63,13 @@ function equalAppInfo(left: AppInfo, right: AppInfo): boolean {

interface Options {
webpackConfig: Configuration;

// the base public URL for your assets in production. Use this when you want
// to serve all your assets from a different origin (like a CDN) than your
// actual index.html will be served on.
//
// This should be a URL ending in "/".
publicAssetURL?: string;
}

// we want to ensure that not only does our instance conform to
Expand All @@ -74,6 +82,7 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {
pathToVanillaApp: string;
private extraConfig: Configuration | undefined;
private passthroughCache: Map<string, Stats> = new Map();
private publicAssetURL: string | undefined;

constructor(
pathToVanillaApp: string,
Expand All @@ -83,7 +92,8 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {
options?: Options
) {
this.pathToVanillaApp = realpathSync(pathToVanillaApp);
this.extraConfig = options && options.webpackConfig;
this.extraConfig = options?.webpackConfig;
this.publicAssetURL = options?.publicAssetURL;
warmUp();
}

Expand All @@ -102,19 +112,21 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {
let resolvableExtensions = meta['resolvable-extensions'];
let entrypoints = [];
let otherAssets = [];
let publicAssetURL = this.publicAssetURL || rootURL;

for (let relativePath of meta.assets) {
if (/\.html/i.test(relativePath)) {
entrypoints.push(new HTMLEntrypoint(this.pathToVanillaApp, rootURL, relativePath));
entrypoints.push(new HTMLEntrypoint(this.pathToVanillaApp, rootURL, publicAssetURL, relativePath));
} else {
otherAssets.push(relativePath);
}
}
return { entrypoints, otherAssets, templateCompiler, babel, rootURL, resolvableExtensions };

return { entrypoints, otherAssets, templateCompiler, babel, rootURL, resolvableExtensions, publicAssetURL };
}

private configureWebpack(
{ entrypoints, templateCompiler, babel, rootURL, resolvableExtensions }: AppInfo,
{ entrypoints, templateCompiler, babel, resolvableExtensions, publicAssetURL }: AppInfo,
variant: Variant
): Configuration {
let entry: { [name: string]: string } = {};
Expand Down Expand Up @@ -166,7 +178,7 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {
path: join(this.outputPath, 'assets'),
filename: `chunk.[chunkhash].js`,
chunkFilename: `chunk.[chunkhash].js`,
publicPath: rootURL + 'assets/',
publicPath: publicAssetURL + 'assets/',
},
optimization: {
splitChunks: {
Expand Down Expand Up @@ -273,7 +285,7 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {
}
}

private async writeFiles(stats: StatSummary, { entrypoints, otherAssets, rootURL }: AppInfo) {
private async writeFiles(stats: StatSummary, { entrypoints, otherAssets }: AppInfo) {
// we're doing this ourselves because I haven't seen a webpack 4 HTML plugin
// that handles multiple HTML entrypoints correctly.

Expand Down Expand Up @@ -333,7 +345,7 @@ const Webpack: Packager<Options> = class Webpack implements PackagerInstance {

for (let entrypoint of entrypoints) {
ensureDirSync(dirname(join(this.outputPath, entrypoint.filename)));
writeFileSync(join(this.outputPath, entrypoint.filename), entrypoint.render(stats, rootURL), 'utf8');
writeFileSync(join(this.outputPath, entrypoint.filename), entrypoint.render(stats), 'utf8');
written.add(entrypoint.filename);
}

Expand Down
28 changes: 19 additions & 9 deletions packages/webpack/src/html-entrypoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ export class HTMLEntrypoint {
scripts: string[] = [];
styles: string[] = [];

constructor(private pathToVanillaApp: string, private rootURL: string, public filename: string) {
constructor(
private pathToVanillaApp: string,
private rootURL: string,
private publicAssetURL: string,
public filename: string
) {
this.dom = new JSDOM(readFileSync(join(this.pathToVanillaApp, this.filename), 'utf8'));

for (let tag of this.handledStyles()) {
Expand Down Expand Up @@ -72,9 +77,10 @@ export class HTMLEntrypoint {
}

// bundles maps from input asset to a per-variant map of output assets
render(stats: StatSummary, rootURL: string): string {
render(stats: StatSummary): string {
let insertedLazy = false;
let fastbootVariant = stats.variants.findIndex(v => Boolean(v.runtime === 'fastboot'));
let supportsFastboot = stats.variants.some(v => v.runtime === 'fastboot' || v.runtime === 'all');

for (let [src, placeholders] of this.placeholders) {
let match = stats.entrypoints.get(src);
Expand All @@ -84,24 +90,28 @@ export class HTMLEntrypoint {
let matchingFastbootBundles = fastbootVariant >= 0 ? match.get(fastbootVariant) || [] : [];

for (let placeholder of placeholders) {
insertedLazy = maybeInsertLazyBundles(insertedLazy, stats.lazyBundles, placeholder, rootURL);
if (supportsFastboot) {
// if there is any fastboot involved, we will emit the lazy bundles
// right before our first script.
insertedLazy = maybeInsertLazyBundles(insertedLazy, stats.lazyBundles, placeholder, this.publicAssetURL);
}
for (let [base, fastboot] of zip(matchingBundles, matchingFastbootBundles)) {
if (!base) {
// this bundle only exists in the fastboot variant
let element = placeholder.start.ownerDocument.createElement('fastboot-script');
element.setAttribute('src', rootURL + fastboot);
element.setAttribute('src', this.publicAssetURL + fastboot);
placeholder.insert(element);
placeholder.insertNewline();
} else if (!fastboot || base === fastboot) {
// no specialized fastboot variant
let src = rootURL + base;
let src = this.publicAssetURL + base;
placeholder.insertURL(src);
} else {
// we have both and they differ
let src = rootURL + base;
let src = this.publicAssetURL + base;
let element = placeholder.insertURL(src);
if (element) {
element.setAttribute('data-fastboot-src', rootURL + fastboot);
element.setAttribute('data-fastboot-src', this.publicAssetURL + fastboot);
}
}
}
Expand Down Expand Up @@ -129,12 +139,12 @@ function maybeInsertLazyBundles(
insertedLazy: boolean,
lazyBundles: Set<string>,
placeholder: Placeholder,
rootURL: string
publicAssetURL: string
): boolean {
if (!insertedLazy && placeholder.isScript()) {
for (let bundle of lazyBundles) {
let element = placeholder.start.ownerDocument.createElement('fastboot-script');
element.setAttribute('src', rootURL + bundle);
element.setAttribute('src', publicAssetURL + bundle);
placeholder.insert(element);
placeholder.insertNewline();
}
Expand Down

0 comments on commit b4106a7

Please sign in to comment.