当前位置: 首页 > Web前端 > JavaScript

新一代编译工具SWC

时间:2023-03-27 18:11:49 JavaScript

最近在前端圈掀起了一股Rust风潮。任何可以用Rust重写的前端工具都应该用Rust重写。今天介绍的工具是rust实现的babel:swc,一个ES6转ES5的工具。而且在swc的官网上,很直白的说是对标babel,swc和babel的命令是可以互相替换的,babel的大部分插件也都实现了。使用Rust的优势之一是速度。比如我们之前的一个项目,把babel换成swc后,编译速度从7秒提升到1秒,效率直接爆炸。swc入门和babel一样,将命令行工具和编译核心模块分成两个包。@swc/cli类似于@babel/cli;@swc/core类似于@babel/core;npmi-D@swc/cli@swc/core可以通过以下命令将ES6JS文件转换为ES5。npxswcsource.js-odist.js下面是source.js的代码:conststart=()=>{console.log('appstarted')}代码包含了ES6的两个特性,const声明和箭头功能。经过swc改造后,这两个特征分别被改造为var声明和function匿名函数。配置文件swc和babel一样,支持类似.babelrc的配置文件:.swcrc,配置格式为JSON。{"jsc":{//编译规则"target":"es5",//输出js规范"parser":{//除了ecmascript,还支持typescript"syntax":"ecmascript",//是否解析jsx,对应插件@babel/plugin-transform-react-jsx"jsx":false,//是否支持装饰器,对应插件@babel/plugin-syntax-decorators"decorators":false,//是否支持动态导入,对应的Plugin@babel/plugin-syntax-dynamic-import"dynamicImport":false,//...//大部分babel的插件都可以在这里找到对应的配置},"minify":{},//压缩相关配置,需要先开启Compression},"env":{//编译结果相关配置"targets":{//编译结果需要适配的浏览器"ie":"11"//只兼容ie11},"corejs":"3"//corejs版本},"minify":true//是否开启压缩}babel的插件系统集成在配置中injsc.parserbyswc,基本上大部分插件都能搞定。而且swc还继承了压缩的能力,通过minify属性开启,jsc.minify用于配置压缩相关的规则。更详细的配置请参考文档。NodeAPIs通过在node.js代码中引入@swc/core模块,可以调用node.js中的api直接编译代码,是CLI工具开发的常规操作。//swc.mjsimport{readFileSync}from'fs'import{transform}from'@swc/core'construn=async()=>{constcode=readFileSync('./source.js','utf-8')constresult=awaittransform(code,{filename:"source.js",})//输出编译后的代码console.log(result.code)}run()除了代码转义,swc还提供了一个简单的包装能力。我们新建一个src文件夹,在里面新建两个文件:index.js和utils.js。//src/index.jsimport{log}from'./utils.js'conststart=()=>log('appstarted')start()//src/utils.jsexportconstlog=function(){console.log(...arguments)}exportconsterrorLog=function(){console.error(...arguments)}可以看到index.js在utils.js中引入了一个方法,然后我们新建一个spack。config.js文件,这是swc打包的配置文件。//spack.config.jsmodule.exports={entry:{//打包入口web:__dirname+"/src/index.js",},output:{//打包输出文件夹路径:__dirname+"/dist",},};然后在命令行运行:$npxspack打包成功后,会在dist目录下输出一个web.js文件。可以看出,不仅将index.js和utils.js打包成一个文件,还进行了treeshaking,删除了utils.js中不用的errorLog方法。可以用吗?毕竟经过这么多年的发展,babel无论是在bug减少还是在社区活跃度上,都远远优于swc。所以,如果是试水的小产品,还是可以试试swc的。如果老项目已经使用了babel,不建议迁移。在使用过程中,还是发现了一些小问题。例如,如果我使用async函数,swc将自动导入regenerator-runtime模块。//编译前有个async方法conststart=async()=>{console.log('appstarted')}callsswc编译后代码如下:这个结果好像没问题,但是swc是和babel类似,也有helpers(@swc/helpers),也提供了externalHelpers开关,如果externalHelpers设置为true,swc会以模块的形式引入一些工具类。//.swcrc{"jsc":{"externalHelpers":true}}externalHelpers的默认值为false。这个时候regenerator-runtime是应该以模块的形式引入,还是应该把整个代码写到一个文件中?swc正好有个[issue[https://github.com/swc-projec...]](https://github.com/swc-projec...)讨论这个问题。除了上面提到的问题,其实还有一点,就是作者觉得之前的架构有问题,正在加紧重写2.0版本。大学还没毕业,最后只能说一句:太棒了!