如何在React项目中不使用CDN全局暴露CryptoJS以支持外部非模块脚本调用
如何在React项目中不使用CDN全局暴露CryptoJS以支持外部非模块脚本调用
我来帮你搞定这个问题!要在React项目里不依赖CDN全局暴露CryptoJS,让index.html中的非模块脚本能安全调用它的加密函数,你可以按照以下步骤一步步操作:
1. 本地安装CryptoJS包
首先移除原来CDN的引入,改用包管理工具安装本地版本:
# npm npm install crypto-js # 或者yarn yarn add crypto-js
2. 在React入口文件全局挂载CryptoJS
React的入口文件(通常是src/main.tsx或src/main.jsx)是ES模块,内部变量默认不会全局暴露。我们需要手动将CryptoJS挂载到window对象上,这样非模块脚本就能访问到它:
TypeScript版本(main.tsx)
import CryptoJS from 'crypto-js'; import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; // 全局暴露CryptoJS到window对象 // 如果你想获得类型提示,可以扩展Window接口(见下文可选优化) (window as any).CryptoJS = CryptoJS; // 正常渲染你的React应用 ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <App /> </React.StrictMode>, );
JavaScript版本(main.jsx)
import CryptoJS from 'crypto-js'; import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; // 直接挂载到window window.CryptoJS = CryptoJS; ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <App /> </React.StrictMode>, );
可选:TypeScript类型优化(获得类型提示)
如果你用TypeScript,不想每次都用(window as any),可以扩展Window接口来添加CryptoJS的类型定义:
在src/types目录下创建crypto-js.d.ts文件:
import CryptoJS from 'crypto-js'; declare global { interface Window { CryptoJS: typeof CryptoJS; } }
之后就可以直接用window.CryptoJS = CryptoJS,不用类型断言了。
3. 调整index.html中的非模块脚本
接下来修改index.html,移除CDN脚本,同时注意执行时机和语法错误(你原来的代码里有个scipt拼写错误,已经修正):
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Sample</title> </head> <body> <div id="root"></div> <!-- React模块脚本先加载,确保CryptoJS被挂载到window --> <script type="module" src="/src/main.tsx"></script> <!-- 非模块脚本放在React脚本之后,或用事件确保加载完成 --> <script> // 用DOMContentLoaded事件确保React和CryptoJS都已初始化完成 window.addEventListener('DOMContentLoaded', () => { // 注意:请确保publicKey和salt变量在此处已存在 // 如果这些变量来自React应用,你可能需要通过自定义事件/全局变量传递 const keyBytes = CryptoJS.PBKDF2( publicKey, CryptoJS.enc.Hex.parse( Array.from(salt) .map((b) => b.toString(16).padStart(2, '0')) .join(''), ), { keySize: 12, iterations: 10000, hasher: CryptoJS.algo.SHA256, }, ); // 这里可以添加keyBytes的后续处理逻辑 console.log('生成的密钥字节:', keyBytes); }); </script> </body> </html>
关键注意事项
- 执行时机:一定要确保非模块脚本在React入口脚本之后执行,或者用
DOMContentLoaded事件监听,否则会出现CryptoJS is not defined的错误——因为React模块还没来得及把CryptoJS挂载到window上。 - 变量传递:如果你的
publicKey或salt是从React应用内部生成的,不能直接在非模块脚本中访问,需要通过全局变量或自定义事件来传递数据(比如在React中触发一个自定义事件,非模块脚本监听该事件并接收参数)。 - 语法修正:你原来的代码里把
script拼写成了scipt,这个小错误会导致脚本无法执行,已经在示例中修正。
内容来源于stack exchange
相关产品推荐
相关产品推荐

