xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

字符串拼接的压缩策略 #104

Open xinglie opened 1 year ago

xinglie commented 1 year ago

在做magix-composer打包编译工具的时候(工具地址:https://github.com/thx/magix-composer ),我们需要把html文件翻译成js函数并内置到宿主js文件中。

html文件在翻译的过程中少不了要对一些变量和已经存在的html内容做字符串的拼接,本篇主要讨论如何以节省字符的方式进行拼接,让magix-composer编译出的代码人工也无法再优化压缩。

我们先看一种情况:

html content and var:{{=expr}}

面向未来及代码可读性(虽然没有开发者去阅读编译后的代码),我们应该采用模板字符串的方式进行拼接生成,如下

let html=`html content and var:${expr}`

本以为html content and var:${expr}经过压缩器会生成如下的代码

let a='html content and var:'+b;//b 就是前面expr压缩后的变量

实际上大部分压缩器还是保持着模板字符串,如下

let a=`html content and var:${b}`;

显然a${b}的长度要比a+b多2个字符。

如果我们编译中大型项目,有成百上千的html文件,我们把字符串拼接用最少字符的方式拼接,节省的字节数也是很可观的。

情况讨论

`a${b}${c}`

如果变量连续出现在末尾,则我们把末尾的变量直接使用+拼接则是最优的拼接方式,如`a${b}${c}` 变成'a'+b+c可节省4个字符

`a${b}c`

如果变量出现在字符串中间且只有一个,则保持不变,不能使`a${b}c`变成'a'+b+'c',这样反而多出2个字符

`a${b}${c}d`

如果变量出现在字符串中间且连续2个以上,则需要使用+拼接,如`a${b}${c}d`变成'a'+b+c+'d'可节省1个字符

注意不可以变成`a${b+c}d`,虽然这样更省字符,但有可能b和c为数字,会导致它们直接累加,而不是字符串的拼接

`${a}b`

如果变量出现在字符串的开头且只有一个,则需要使用+拼接,如`${a}b`变成a+'b'可节省2个字符

`${a}${b}c`

如果变量出现在字符串的开头且连续2个以上,该情况需要特殊处理,我们不能直接把`${a}${b}c`优化成a+b+'c'。

假如a是数字2,b是数字3,优化前`${a}${b}c`的结果是 23c ,如果优化成a+b+'c'计算后变成了 5c,这是错误的。

为了安全的转换,我们需要在优化后的第一个变量前面或后面添加一个空字符串,比如优化成 a+''+b+'c'。优化后仍然比优化前节省1个字符

`${a}${b}`

全变量的情况,该情况仍然需要在第一个变量的前面或后面添加一个空字符串, `${a}${b}`变成a+''+b。节省4个字符

无论多复杂的模板字符串均可拆分成如上的组成情况,我们通过识别变量在模板字符串中的位置(前,中,后)和是否连续(变量前或后是否还有其它变量),再套用如上的优化策略即可输出最优的字符串拼接。

目前magix-composer支持输出时,能对字符串拼接自动做如上的优化,力求做到输出的代码人工也无法优化压缩。