为什么需要ES5的代码
最近在开发公司的一个项目时,为了最小化代码文件,就上手尝试了一下svelte,这个目前号称编译后代码包最小的框架,通过把大部分的计算放在编译时进行,而不是在运行时进行,从而极大程度上减少了运行时库文件的大小
目前来说,效果很棒,完成一些简单的功能开发之后,整个production模式下编译的代码包在70KB左右,gzip之后的体积是26.5KB,可以说是很惊艳了。不跟React
比,跟同样号称代码包很小的Vue.js
比,Vue.js项目,不说业务代码,单单库文件(v2.6.10版本)就有83KB了。
不过有一点问题是,svelte官方认为目前浏览器大部分都已经支持了ES6,所以他们提交到npm的runtime的代码也是直接输出的es6的代码。
一开始我也比较认可这个说法的,自己的项目代码也输出的es6,然后上线了。
之后我发现国外的浏览器跟国内还是不一样的进化程度。这个项目是有用fundebug来做错误监控的,上线没多久之后,错误就一直不断
所以还是需要面对现实,代码还是ES5的香,就像当初为了兼容IE6,7时候写ES3的代码一样
事情没那么简单
首先是自己的业务代码,是基于babel
进行代码转换的,用的@babel/preset-env
,配置的targets值为> 2% in CN, last 2 major versions, not dead
不过可能我们业务面对的用户群跟 browserslist-compatible 收集的数据不太匹配,编译后的代码里面const, arrow function, spread等等特性的代码都还在,没办法,又只好手动指定来一些plugin,最终的.babelrc内容如下:
{
"presets": [
[
"@babel/preset-env",
{
"targets": "> 2% in CN, last 2 major versions, not dead",
"debug": true,
"include": [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-spread",
"@babel/plugin-transform-destructuring",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-parameters"
]
}
]
]
}
这番配置之后,业务代码是已经都转换为ES5的了,可是从svelte import过来的代码,却没有被正确转换为ES5的。
在网上搜了一些解决方案,一个svelte-loader里面的issue给了一个解决方案,思路是使用loader进行相应格式文件处理的时候,把node_modules/svelte/
模块下的文件也处理一下
尝试了一下,发现并不可以,也不知道是svelte的版本升级之后不兼容,还是我这边配置有问题
自行编译svelte
最后我想,既然我没法在项目里面把svelte的runtime代码丢给babel处理,那不如从源头解决这个问题。git clone下来svelte,编译为es5的代码,然后在用yarn link的方式引用到业务项目里面
因为svelte是基于typescript编写的,当时在我看来,改编译为es5很简单,直接在tsconfig.json
里面把targets改成es5,然后运行npm run build
命令来重新编译即可。
可是不行。
再仔细看了一下rollup.config.js
import sucrase from 'rollup-plugin-sucrase';
import typescript from 'rollup-plugin-typescript';
const ts_plugin = is_publish
? typescript({
include: 'src/**',
typescript: require('typescript')
})
: sucrase({
transforms: ['typescript']
});
在publish环境下使用typescript来编译ts文件,其他情况下使用Sucrase来编译ts文件
很奇怪的是,build命令并没有设定环境为publish。而Sucrase,看了一下,是一个Babel的替代品,为了加快编译速度,编译出来的代码都是面向现代浏览器,也就是没有什么语法转换和polyfill的。
为了能够使用typescript来编译,调整了一下package.json里面的build命令
从rollup -c && npm run tsd
改成PUBLISH=true rollup -c && npm run tsd
再重新执行build命令,成功。
然后再回到已经把svelte link到本地的业务项目,重新编译。这次编译,svelte runtime相关代码就成功使用了基于es5编译的。