最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - Angular 19 with SSR is not able to build with ReferenceError: __dirname is not defined - Stack Overflow

programmeradmin1浏览0评论

I am trying to use google-cloud/secret-manager in the server side code for an Angular 19 SSR application. However, when I build or serve in dev, it throws the below error:

Watch mode enabled. Watching for file changes...
NOTE: Raw file sizes do not reflect development server per-request transformations.
  ➜  Local:   http://localhost:4200/
  ➜  press h + enter to show help

11:19:30 AM [vite] (ssr) Error when evaluating SSR module ./server.mjs:
|- ReferenceError: __dirname is not defined
    at node_modules/google-gax/build/src/grpc.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:38145:41)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/google-gax/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:54580:18)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/secret_manager_service_client.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:55012:24)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:56261:43)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:78769:14)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)

ReferenceError: __dirname is not defined
    at node_modules/google-gax/build/src/grpc.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:38145:41)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/google-gax/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:54580:18)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/secret_manager_service_client.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:55012:24)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:56261:43)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:78769:14)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)

Going through the Angular 19 documentation, it mentions that third-party libraries can have CommonJS constructs. My project is, however, a fresh project.

Now on the google-cloud/secret-manager library, it uses google-gax and probably this package uses __dirname construct in it.

Found similar issue from google-cloud-node repository, but not able to fit the solution into current Angular build system.

What I have tried till now is upgraded @google-cloud/secret-manager to the latest available version (6.0.1), which in case upgrades google-gax (5.0.1-rc.0) as well. Both provide TypeScript support as per NPM packages.

Steps to replicate:

  1. Ensure node v18.x.x is installed
  2. Create a SSR application
npm install -g @angular/[email protected]
ng new --ssr
cd <project_directory>
npm i @google-cloud/secret-manager
  1. Modify the contents of the file src/server.ts:
import {
  AngularNodeAppEngine,
  createNodeRequestHandler,
  isMainModule,
  writeResponseToNodeResponse,
} from '@angular/ssr/node';
import express from 'express';
import { v1 } from '@google-cloud/secret-manager';
import { Application } from 'express';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');

const app = express();
const angularApp = new AngularNodeAppEngine();

const secretManagerClient = new v1.SecretManagerServiceClient();

async function fetchSecretByName(secretName: string): Promise<string | undefined> {
  const [version] = await secretManagerClient.accessSecretVersion({ name: secretName });
  const value = version.payload?.data?.toString();

  return value;
}

function initializeSecretCreds(app: Application): void {
  const secretPath = "projects/<gcp-project-id-number>/secrets/<secret-name>";

  if (!secretPath) {
    process.exit(1);
  }

  let value = null;
  fetchSecretByName(`${secretPath}/versions/latest`)
    .then(secret => {
      value = secret;
      if (!value) {
        process.exit(1);
      }
      const secretValue = JSON.parse(value);
      // do something with the secret value
    })
    .catch(err => {
      process.exit(1);
    })
}


app.use(
  express.static(browserDistFolder, {
    maxAge: '1y',
    index: false,
    redirect: false,
  }),
);

/**
 * Handle all other requests by rendering the Angular application.
 */
app.use('/**', (req, res, next) => {
  angularApp
    .handle(req)
    .then((response) =>
      response ? writeResponseToNodeResponse(response, res) : next(),
    )
    .catch(next);
});

/**
 * Start the server if this module is the main entry point.
 * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
 */
if (isMainModule(import.meta.url)) {
  const port = process.env['PORT'] || 4000;
  initializeSecretCreds(app);
  app.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

/**
 * Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions.
 */
export const reqHandler = createNodeRequestHandler(app);

Has anyone faced a similar issue with Angular 19 SSR and come up with a solution or any workaround for the same?

I am trying to use google-cloud/secret-manager in the server side code for an Angular 19 SSR application. However, when I build or serve in dev, it throws the below error:

Watch mode enabled. Watching for file changes...
NOTE: Raw file sizes do not reflect development server per-request transformations.
  ➜  Local:   http://localhost:4200/
  ➜  press h + enter to show help

11:19:30 AM [vite] (ssr) Error when evaluating SSR module ./server.mjs:
|- ReferenceError: __dirname is not defined
    at node_modules/google-gax/build/src/grpc.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:38145:41)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/google-gax/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:54580:18)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/secret_manager_service_client.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:55012:24)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:56261:43)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:78769:14)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)

ReferenceError: __dirname is not defined
    at node_modules/google-gax/build/src/grpc.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:38145:41)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/google-gax/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:54580:18)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/secret_manager_service_client.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:55012:24)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/v1/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:56261:43)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)
    at node_modules/@google-cloud/secret-manager/build/src/index.js (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\@google-cloud_secret-manager.js:78769:14)
    at __require2 (C:\Users\user1\repositories\ssr-wbsite\.angular\cache\19.1.8\company-ssr-wbsite\vite\deps_ssr\chunk-GBTWTWDP.js:52:50)

Going through the Angular 19 documentation, it mentions that third-party libraries can have CommonJS constructs. My project is, however, a fresh project.

Now on the google-cloud/secret-manager library, it uses google-gax and probably this package uses __dirname construct in it.

Found similar issue from google-cloud-node repository, but not able to fit the solution into current Angular build system.

What I have tried till now is upgraded @google-cloud/secret-manager to the latest available version (6.0.1), which in case upgrades google-gax (5.0.1-rc.0) as well. Both provide TypeScript support as per NPM packages.

Steps to replicate:

  1. Ensure node v18.x.x is installed
  2. Create a SSR application
npm install -g @angular/[email protected]
ng new --ssr
cd <project_directory>
npm i @google-cloud/secret-manager
  1. Modify the contents of the file src/server.ts:
import {
  AngularNodeAppEngine,
  createNodeRequestHandler,
  isMainModule,
  writeResponseToNodeResponse,
} from '@angular/ssr/node';
import express from 'express';
import { v1 } from '@google-cloud/secret-manager';
import { Application } from 'express';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');

const app = express();
const angularApp = new AngularNodeAppEngine();

const secretManagerClient = new v1.SecretManagerServiceClient();

async function fetchSecretByName(secretName: string): Promise<string | undefined> {
  const [version] = await secretManagerClient.accessSecretVersion({ name: secretName });
  const value = version.payload?.data?.toString();

  return value;
}

function initializeSecretCreds(app: Application): void {
  const secretPath = "projects/<gcp-project-id-number>/secrets/<secret-name>";

  if (!secretPath) {
    process.exit(1);
  }

  let value = null;
  fetchSecretByName(`${secretPath}/versions/latest`)
    .then(secret => {
      value = secret;
      if (!value) {
        process.exit(1);
      }
      const secretValue = JSON.parse(value);
      // do something with the secret value
    })
    .catch(err => {
      process.exit(1);
    })
}


app.use(
  express.static(browserDistFolder, {
    maxAge: '1y',
    index: false,
    redirect: false,
  }),
);

/**
 * Handle all other requests by rendering the Angular application.
 */
app.use('/**', (req, res, next) => {
  angularApp
    .handle(req)
    .then((response) =>
      response ? writeResponseToNodeResponse(response, res) : next(),
    )
    .catch(next);
});

/**
 * Start the server if this module is the main entry point.
 * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
 */
if (isMainModule(import.meta.url)) {
  const port = process.env['PORT'] || 4000;
  initializeSecretCreds(app);
  app.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

/**
 * Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions.
 */
export const reqHandler = createNodeRequestHandler(app);

Has anyone faced a similar issue with Angular 19 SSR and come up with a solution or any workaround for the same?

Share Improve this question asked Mar 31 at 9:03 adityaprakashadityaprakash 246 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Given the third party library here, @google-cloud/secret-manager might not support ESM as of now, probably found a way around to the __dirname issue by making use of google-api-nodejs-client which is a wrapper over the Google REST APIs. Given this library has full typescript support, we can utilize the it to perform the same functionality of fetching secret value. The function mentioned above to fetch the secret value can be refactored in the given snippet:

...
// import { v1 } from '@google-cloud/secret-manager'; -- removed
import { google } from 'googleapis';
...

...
// const secretManagerClient = new v1.SecretManagerServiceClient(); -- removed

async function fetchSecretByName(secretName: string): Promise<string | undefined> { // refactored
  const auth = new google.auth.GoogleAuth();

  // obtain the current project Id
  const project = await auth.getProjectId();

  // build secret manager client
  const secretManager = google.secretmanager({ auth: auth, version: 'v1' });
  
  // fetch the secret value
  const res = await secretManager.projects.secrets.versions.access({
    name: secretName,
  })

  return Buffer.from(res.data.payload?.data?.toString() as string, 'base64').toString('utf8');
}

This helped overcome the issue of google-gax used in google-cloud-node library. Hope this comes in help to someone facing a similar issue of google-cloud-node in Angular 19 SSR.

发布评论

评论列表(0)

  1. 暂无评论