You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 14使用crypto-js遇CommonJS优化警告,求非忽略式解决方案

问题描述

我正在开发Angular 14项目,编写了如下代码用于生成哈希值:

import {Injectable} from '@angular/core';
import {enc, lib, SHA256} from 'crypto-js';

@Injectable({
  providedIn: 'root'
})
export class CryptoService {

  constructor() {
  }

  static generateCodeVerifier() {
    return this.base64Url(enc.Base64.stringify(lib.WordArray.random(32)));
  }

  static generateCodeChallenge() {
    const codeVerifier = sessionStorage.getItem('codeVerifier');
    return codeVerifier != null ? this.base64Url(SHA256(codeVerifier)) : '';
  }

  private static base64Url(str: any) {
    return str.toString()
    .replace(/=/g, '')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');
  }
}

打包应用时出现如下警告:

/crypto.service.ts depends on 'crypto-js'. CommonJS or AMD dependencies can cause optimization bailouts. For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies

我知道可通过在angular.json的allowedCommonJsDependencies中添加该依赖来忽略警告,但了解相关情况后不想这么做。请问有什么解决办法?我也愿意使用其他替代库。

解决方案

方案一:用原生Web Crypto API替代(无需额外依赖)

现代浏览器原生支持Web Crypto API,这是标准加密接口,完全符合ESM规范,不会触发优化警告。重写后的CryptoService如下:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CryptoService {

  constructor() { }

  static async generateCodeVerifier(): Promise<string> {
    const randomBytes = new Uint8Array(32);
    window.crypto.getRandomValues(randomBytes);
    return this.base64Url(randomBytes);
  }

  static async generateCodeChallenge(): Promise<string> {
    const codeVerifier = sessionStorage.getItem('codeVerifier');
    if (!codeVerifier) return '';

    const encoder = new TextEncoder();
    const encodedVerifier = encoder.encode(codeVerifier);
    const hashBuffer = await window.crypto.subtle.digest('SHA-256', encodedVerifier);
    
    return this.base64Url(new Uint8Array(hashBuffer));
  }

  private static base64Url(array: Uint8Array): string {
    return btoa(String.fromCharCode(...array))
      .replace(/=/g, '')
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
  }
}

注意:Web Crypto API的部分方法是异步的,所以两个生成方法需要改为异步函数,调用时要使用await或者.then()处理结果。

方案二:使用ESM格式的替代库

如果偏好使用第三方库,可以选择@noble/hashes——这是一个轻量、树摇友好的纯ESM库,完全兼容Angular的优化机制,不会触发CommonJS相关警告。

  1. 安装依赖:
npm install @noble/hashes
  1. 重写CryptoService:
import { Injectable } from '@angular/core';
import { sha256 } from '@noble/hashes/sha256';
import { randomBytes } from '@noble/hashes/utils';

@Injectable({
  providedIn: 'root'
})
export class CryptoService {

  constructor() { }

  static generateCodeVerifier(): string {
    const bytes = randomBytes(32);
    return this.base64Url(bytes);
  }

  static generateCodeChallenge(): string {
    const codeVerifier = sessionStorage.getItem('codeVerifier');
    if (!codeVerifier) return '';

    const hash = sha256(codeVerifier);
    return this.base64Url(hash);
  }

  private static base64Url(bytes: Uint8Array): string {
    return btoa(String.fromCharCode(...bytes))
      .replace(/=/g, '')
      .replace(/\+/g, '-')
      .replace(/\//g, '_');
  }
}

这个库体积比crypto-js更小,同时支持树摇,能让打包后的代码更精简。

内容的提问来源于stack exchange,提问作者sanurah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:20:41