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

Angular v17 support #6480

Merged
merged 17 commits into from
Nov 17, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Enable [preferRest](https://firebase.google.com/docs/reference/admin/node/firebase-admin.firestore.firestoresettings.md#firestoresettingspreferrest) option by default for Firestore functions. (#6147)
- Fixed a bug where re-deploying 2nd Gen Firestore function failed after updating secrets. (#6456)
- Added the ability to deploy Angular apps using the new application-builder. (#6480)
34 changes: 25 additions & 9 deletions src/frameworks/angular/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ export async function init(setup: any, config: any) {
export async function build(dir: string, configuration: string): Promise<BuildResult> {
Copy link
Contributor

@9kubczas4 9kubczas4 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should mark useAngularUniversal in the init function as legacy?

  const useAngularUniversal = await promptOnce({
    name: "useAngularUniversal",
    type: "confirm",
    default: false,
    message: `Would you like to setup Angular Universal?`,
  });
  if (useAngularUniversal) {
    execSync("ng add @nguniversal/express-engine --skip-confirmation", {
      stdio: "inherit",
      cwd: join(config.projectDir, setup.hosting.source),
    });
  }

Cause NG CLI in v17 is asking about Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I should rework the bootstrap. It should be part of Angular's create routine now

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are using @angular/cli@latest, @nguniversal/express-engine should not be used as this is only supported for version 16 and before.

const {
targets,
serverTarget,
serveOptimizedImages,
locales,
baseHref: baseUrl,
ssr,
} = await getBuildConfig(dir, configuration);
await warnIfCustomBuildScript(dir, name, DEFAULT_BUILD_SCRIPT);
for (const target of targets) {
Expand All @@ -84,8 +84,8 @@ export async function build(dir: string, configuration: string): Promise<BuildRe
if (result.status !== 0) throw new FirebaseError(`Unable to build ${target}`);
}

const wantsBackend = !!serverTarget || serveOptimizedImages;
const rewrites = serverTarget
const wantsBackend = ssr || serveOptimizedImages;
const rewrites = ssr
? []
: [
{
Expand Down Expand Up @@ -149,8 +149,12 @@ export async function ɵcodegenPublicDirectory(
export async function getValidBuildTargets(purpose: BUILD_TARGET_PURPOSE, dir: string) {
const validTargetNames = new Set(["development", "production"]);
try {
const { workspaceProject, browserTarget, serverTarget, serveTarget } = await getContext(dir);
const { target } = ((purpose === "emulate" && serveTarget) || serverTarget || browserTarget)!;
const { workspaceProject, buildTarget, browserTarget, prerenderTarget, serveTarget } =
await getContext(dir);
const { target } = ((purpose === "emulate" && serveTarget) ||
buildTarget ||
prerenderTarget ||
browserTarget)!;
const workspaceTarget = workspaceProject.targets.get(target)!;
Object.keys(workspaceTarget.configurations || {}).forEach((it) => validTargetNames.add(it));
} catch (e) {
Expand Down Expand Up @@ -182,6 +186,7 @@ export async function ɵcodegenFunctionsDirectory(
externalDependencies,
baseHref,
serveOptimizedImages,
serverEntry,
} = await getServerConfig(sourceDir, configuration);

const dotEnv = { __NG_BROWSER_OUTPUT_PATH__: browserOutputPath };
Expand Down Expand Up @@ -232,14 +237,25 @@ exports.handle = function(req,res) {
if (localizedApps.has(locale)) {
localizedApps.get(locale)(req,res);
} else {
const app = require(\`./${serverOutputPath}/\${locale}/main.js\`).app(locale);
localizedApps.set(locale, app);
app(req,res);
${
serverEntry?.endsWith(".mjs")
? `import(\`./${serverOutputPath}/\${locale}/${serverEntry}\`)`
: `Promise.resolve(require(\`./${serverOutputPath}/\${locale}/${serverEntry}\`))`
}.then(server => {
const app = server.app(locale);
localizedApps.set(locale, app);
app(req,res);
});
}
});
};\n`;
} else if (serverOutputPath) {
bootstrapScript = `exports.handle = require('./${serverOutputPath}/main.js').app();\n`;
bootstrapScript = `const app = ${
serverEntry?.endsWith(".mjs")
? `import(\`./${serverOutputPath}/${serverEntry}\`)`
: `Promise.resolve(require('./${serverOutputPath}/${serverEntry}'))`
}.then(server => server.app());
exports.handle = (req,res) => app.then(it => it(req,res));\n`;
} else {
bootstrapScript = `exports.handle = (res, req) => req.sendStatus(404);\n`;
rewriteSource = posix.join(baseHref, "__image__");
Expand Down