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相关警告。
- 安装依赖:
npm install @noble/hashes
- 重写
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
相关产品推荐
相关产品推荐

