i18n treeshaking 顾名思义,就如同 webpack 的 treeshaking(树摇晃) 操作一样,去掉没有使用的i18n国际化键值对。
好久没有更新博客了,去年下半年迷一样的状态,,一月放假,疫情又懒得动。
中国现在疫情已经到尾声了,但是各个省市依然有输入病例,大家千万不可以松懈,武汉加油,陕西加油,中国加油!!!
从三月底开始,会更新一些项目的解决方案,由平时项目比较关键的点提取出来,后续还会更新微前端
实践方案。
正文开始!!!
思考(Why do this?)
- 项目迭代版本,旧的国际化键值对因为业务变更等因素,很多使用的地方会被新业务覆盖甚至删除。
- 人员变更,新旧人员更替,命名规则方式也很多不相同,有时候为了可维护,会写一套新的键值对。
以上两点随着日积月累,会造成旧的国际化键值对越来越多,维护越来越困难,所以迫切需要一个自动化的脚本来进行对比删除。
代码设计
- 第一步,抓取文件内的国际化键值对,拿所有的key做成一个数组,方便查找
- 第二步,抓取指定文件目录下的js和vue文件
- 第三步,进行对比,找到key的数组内任意一个,则计次1 ,统计所有计次,过滤掉所有计次为 0 的key
- 第四步,抓出国际化数据过滤替换后写入
代码实现
I18nTreeShaking.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
const fs = require('fs'); const path = require('path');
const i18nDirPath = path.join(__dirname, '../src/assets/i18n/lang');
const treeShakingFileName = ['zh-CN.js'];
const diffDirPath = path.join(__dirname, '../src');
async function getI18NKey(i18nDirPath) { try { let i18nDir = fs.readFileSync(i18nDirPath); let i18nObj = {}; i18nDir && i18nDir.forEach(fileName => { let filePath = path.join(i18nDirPath, fileName); let stats = fs.statSync(filePath); if (!stats.isDirectory() && treeShakingFileName.indexOf(fileName) > -1) { i18nObj[fileName] = []; let data = fs.readdirSync(filePath, {encoding: 'utf8'}); data.replace(/\{([\s\S]+)\}/, function (match) { match.split('\n').forEach(row => { let rowText = row.trim(); let key = rowText.match(/(?:[\"|\'])([^\:]+)()(?:[\"|\'])/); key && i18nObj[fileName].push(key[1]); }) }) } }) return i18nObj; } catch (e) { throw e; } }
async function getDiffFilePaths(rootDir) { try { let filePathDirs = readFileList(rootDir) || []; let arr = filePathDirs.filter(item => /.js/.test(item) && item.indexOf('\\lang') === -1 || /.vue/.test(item)); return arr; } catch (e) { throw e; } }
function readFileList(dir, filesList = []) { const files = fs.readdirSync(dir); files.forEach((item, index) => { let fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { readFileList(path.join(dir, item), filesList); } else { filesList.push(fullPath); } }) return filesList; }
async function main() { console.log('Searching for files, Please wait...'); try { let i18nkeyMap = await getI18NKey(i18nDirPath); for (let i18nFileName in i18nkeyMap) { let i18nkeyObj = {}; let i18nRegList = i18nkeyMap[i18nFileName].map(key => { i18nkeyObj[key] = 0; return {key, reg: new RegExp(key, 'g')} });
let diffFilePaths = await getDiffFilePaths(diffDirPath);
diffFilePaths.forEach((filePath, index) => { let fileData = fs.readFileSync(filePath, {encoding: 'utf8'}); i18nRegList.forEach(() => { fileData.replace(reg, function () { i18nkeyObj[key] += 1; }) }) })
let usedKeys = []; let unUsedKeys = []; for (let key in i18nkeyObj) { let times = i18nkeyObj[key]; if (times !== 0) { console.log("Used key -- ", key); usedKeys.push(key); } else { console.log("Unused key -- ", key); unUsedKeys.push(key); } }
} } catch (e) { throw e; } }
module.exports = main().then(()=>{ console.log('I18n file tree shaking success.'); })
|
本文作者: haise
本文地址: https://www.shifeng1993.com/2020/03/28/project_i18n_treeshaking/
版权声明: 转载请注明出处!