NodeJS同步函数调用异步请求及Vue项目CDN Integrity自动生成
Node.js同步函数运行异步函数及Vue CDN Integrity自动生成方案
一、通用问题:Node.js同步函数中运行异步函数的可行方式
Node.js原生API没有直接将异步操作转为同步的机制,但可通过以下两种方式实现:
- 第三方同步HTTP库:使用专门的同步请求库(如
sync-request)替代异步HTTP客户端(如axios),直接在同步函数中发起请求。 - 异步转同步工具包:使用
deasync、sync-kit这类工具将异步函数强制转为同步,但这类工具依赖Node.js内部API,存在版本兼容性风险,且会阻塞事件循环,不建议生产环境使用。
二、具体场景:Vue项目CDN Integrity自动生成的解决方案
针对你需要在vue.config.js中同步生成CDN资源哈希的需求,推荐以下两种可靠方案:
方案1:使用同步HTTP库直接在配置中生成哈希
用sync-request替代axios实现同步资源获取,直接在integrityWapper中完成哈希计算:
function integrityWapper({ css, js }) { const cryptoJS = require('crypto-js'); const hash = cryptoJS.SHA384; const request = require('sync-request'); // 同步获取远程资源内容 const getRemoteContent = (url) => { const response = request('GET', url); return response.getBody('utf8'); }; const icss = css.map(url => { const content = getRemoteContent(url); // 生成符合subresource integrity格式的哈希值 const integrityValue = `sha384-${hash(content).toString(cryptoJS.enc.Base64)}`; return [url, integrityValue]; }); const ijs = js.map(url => { const content = getRemoteContent(url); const integrityValue = `sha384-${hash(content).toString(cryptoJS.enc.Base64)}`; return [url, integrityValue]; }); return { icss, ijs }; } // 在vue.config.js中使用 const cdnConfig = { use: true }; cdnConfig.list = integrityWapper({ css: ['https://cdn.bootcdn.net/ajax/libs/element-plus/2.2.13/index.css'], js: ['https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.prod.min.js'] }); module.exports = defineConfig({ integrity: true, pages: { index: { entry: 'src/main.ts', template: 'public/index.html', filename: 'index.html', CDN: cdnConfig.use ? cdnConfig.list : null } } });
方案2:预先生成哈希配置文件(推荐)
将哈希生成逻辑独立为前置脚本,在构建前执行并生成配置文件,vue.config.js直接读取该文件,避免阻塞构建流程:
- 编写生成脚本
generate-cdn-integrity.js:
const fs = require('fs'); const cryptoJS = require('crypto-js'); const axios = require('axios'); // 定义需要处理的CDN资源列表 const cdnUrls = { css: ['https://cdn.bootcdn.net/ajax/libs/element-plus/2.2.13/index.css'], js: ['https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.prod.min.js'] }; async function generateIntegrityConfig() { const icss = await Promise.all(cdnUrls.css.map(async url => { const response = await axios.get(url); const integrityValue = `sha384-${cryptoJS.SHA384(response.data).toString(cryptoJS.enc.Base64)}`; return [url, integrityValue]; })); const ijs = await Promise.all(cdnUrls.js.map(async url => { const response = await axios.get(url); const integrityValue = `sha384-${cryptoJS.SHA384(response.data).toString(cryptoJS.enc.Base64)}`; return [url, integrityValue]; })); // 将结果写入本地配置文件 fs.writeFileSync('./cdn-integrity-config.json', JSON.stringify({ list: { css: icss, js: ijs } }, null, 2)); } generateIntegrityConfig().catch(err => { console.error('生成CDN哈希失败:', err); process.exit(1); });
- 修改
package.json的构建脚本,添加前置执行步骤:
{ "scripts": { "prebuild": "node generate-cdn-integrity.js", "build": "vue-cli-service build" } }
- 在
vue.config.js中读取预生成的配置:
const cdnIntegrityConfig = require('./cdn-integrity-config.json'); const cdnConfig = { use: true }; module.exports = defineConfig({ integrity: true, pages: { index: { entry: 'src/main.ts', template: 'public/index.html', filename: 'index.html', CDN: cdnConfig.use ? cdnIntegrityConfig.list : null } } });
三、其他方案的可行性分析
- 修改Vue/Webpack配置读取逻辑:不现实,vue-cli的配置加载逻辑是同步固化的,修改源码需要维护自定义版本,成本极高,不推荐。
- 使用deasync/sync-kit转axios为同步:这类工具通过阻塞事件循环实现同步,会导致构建过程卡顿,且依赖Node.js内部API,版本兼容性差,仅适合临时测试场景,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者饕餮饗食
相关产品推荐
相关产品推荐

