Webpack构建时混淆导入的客户翻译文件名方案咨询
解决方案:Webpack构建时哈希化客户翻译文件路径
核心思路
通过构建阶段的脚本+Webpack自定义配置,实现:
- 仓库保留原客户命名的翻译文件(如
en.ford.json) - 构建时自动将客户ID转换为哈希,生成哈希命名的chunk
- 主包仅包含哈希路径映射,不暴露其他客户信息
步骤1:生成客户ID-哈希映射表
先写一个自动化脚本,遍历翻译文件目录,生成客户ID到哈希的映射(避免手动维护)。创建generate-customer-hashes.js:
const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const translationsDir = path.resolve(__dirname, 'client_translations'); const hashMap = {}; fs.readdirSync(translationsDir).forEach(file => { if (!file.endsWith('.json')) return; const [language, customerId] = file.split('.').slice(0, 2); // 用SHA-1生成快速哈希(可替换为其他算法) const hash = crypto.createHash('sha1').update(customerId).digest('hex').slice(0, 16); if (!hashMap[language]) hashMap[language] = {}; hashMap[language][customerId] = hash; // 反向映射供Webpack解析用 hashMap[language][hash] = customerId; }); fs.writeFileSync( path.resolve(__dirname, 'customer-hash-map.json'), JSON.stringify(hashMap, null, 2) );
在package.json的scripts中添加构建前命令:
"scripts": { "prebuild": "node generate-customer-hashes.js", "build": "webpack --mode production" }
步骤2:配置Webpack解析哈希路径
添加自定义解析插件,让Webpack将哈希路径(如en.80ca06ab.json)映射到原客户文件:
const path = require('path'); const webpack = require('webpack'); const customerHashMap = require('./customer-hash-map.json'); class TranslationHashResolver { apply(resolver) { resolver.hooks.resolve.tapAsync('TranslationHashResolver', (req, ctx, callback) => { const match = req.request.match(/^client_translations\/([a-z]{2})\.([0-9a-f]{16})\.json$/); if (!match) return callback(); const [, language, hash] = match; const customerId = customerHashMap[language]?.[hash]; if (!customerId) return callback(); // 将哈希路径替换为原文件路径 const newReq = {...req, request: `client_translations/${language}.${customerId}.json`}; resolver.doResolve(resolver.hooks.resolve, newReq, `Resolved to original file`, ctx, callback); }); } } module.exports = { // 基础配置省略... resolve: { plugins: [new TranslationHashResolver()] }, output: { // 输出chunk用内容哈希命名,彻底隐藏客户信息 chunkFilename: 'client_translation-[contenthash].js' }, optimization: { // 用确定性哈希作为模块/Chunk ID,避免原文件名泄露 moduleIds: 'deterministic', chunkIds: 'deterministic', // 将runtime单独打包,隔离模块映射逻辑 runtimeChunk: 'single' } };
步骤3:修改前端代码,从服务端获取当前客户哈希
禁止在前端打包所有客户的哈希映射,避免泄露客户列表。改为登录后从服务端获取当前客户的哈希值:
// 登录后调用服务端接口获取当前客户的哈希与语言 const fetchClientHash = async () => { const res = await fetch('/api/client-info'); return res.json(); // 返回格式:{ hash: "80ca06abfa1a5104", language: "en" } }; const getClientTranslations = async () => { try { const { hash, language } = await fetchClientHash(); const translations = await import( /* webpackChunkName: "client_translation" */ /* webpackMode: "lazy" */ `client_translations/${language}.${hash}.json` ); return translations.default ?? {}; } catch (err) { console.error('加载客户翻译失败:', err); return {}; } };
步骤4:服务端维护映射表
服务端需要保存customer-hash-map.json中的映射关系,当用户登录后,根据customerId返回对应的哈希和语言,确保前端仅能获取自身的翻译路径。
内容的提问来源于stack exchange,提问作者spassvogel
相关产品推荐
相关产品推荐

