标签: swc

  • 复盘近期升级工具链的过程

    复盘近期升级工具链的过程

    公司希望我提升产品在移动端的体验,于是我就打开了 Lighthouse,然后看了眼代码,发现有几个问题:

    1. 移动端和 pc 端一起编译,共用一套编译配置
    2. 目标平台包括 IE11
    3. 还在使用 babel@6
    4. 全量引用 babel-polyfill
    5. CDN 没有完全 http2

    最后一项联系运维同学解决就好了,我开始尝试解决其它几项。

    0. 目标

    1. 移动端和 pc 端采用不同的编译配置
    2. 尽量用最新的工具链
    3. 兼容 IE11

    1. 尝试升级到 babel@7

    babel@6 停留在 4 年前,存在着各种各样的问题,包括本身的实现和兼容代码都有问题。我希望先升级到 babel@7,以便使用 useBuiltIns: 'usage',减少打包后的代码量。

    实际结果很不理想。升级后代码膨胀了很多,经过研究,发现原因是 core-js 策略比较保守,所以多引用了很多兼容性代码,远远多于 babel@6。

    比较详细的分析可见:babel@6 升级到 babel@7,兼容性代码膨胀的原因

    2. 尝试从 webpack 迁移到 esbuild

    接下来尝试离开 webpack + babel 体系,使用 esbuild。先打包一套 es6 代码,供移动端和现代化浏览器使用,然后再生成一套兼容性代码,给 IE11 使用。

    相比于 webpack + babel,esbuild 的优势是统一+快。按照官网统计,它的速度可能是 webpack 体系的 100 倍。它的问题是只支持 ES6,也不支持扩展,不像 babel 那样,加个插件就能什么标准都支持。

    这次尝试我也失败了。原因倒不是因为 IE11,而是原来的架构跟 webpack 深度耦合,比如:lazy-loading、分割模块、i18n,等。所以迁移成本非常高,发现情况不对之后只好止损。

    3. 使用 esbuild-loader 替换 babel-loader

    webpack 暂时不能放弃,那就用 esbuild-loader 吧,毕竟要快很多。于是就遭遇到上面说的规范问题。

    1. esbuild 只支持标准规范,原本可以通过 babel plugins 支持的特性现在都不支持了,需要改回去
    2. 一些写的不规范的代码,比如变量先使用后定义,在 var 能跑,但是在 letconst 阶段就跑不了,也得改回去

    经过一段时间的折腾,这个尝试还是比较成功。构建时间缩短了一半以上。

    4. 尝试用 babel-standalone 编译 IE11 代码

    上面一步只算完成一半,因为还不支持 IE11。接下来我们计划使用 babel-standalone 实时转译代码。

    babel-standalone 提供在 JS 运行时里实时编译代码的功能,比如做一个在线编辑器,或者应用里内嵌了 V8 等运行时,希望提升兼容性,就可以用这个工具。

    这个尝试失败了,因为 IE11 的 JS 运行时效率太差,我们生产级别的 JS 直接就卡死了,且优化不能。

    5. 尝试用 SWC 在编译时生成 IE11 代码

    SWC 跟 esbuild 比较类似,是另一套新生态尝试,基于 Rust 开发,也能提供极高的编译效率,且支持 ES3。

    我希望能把需要在 IE11 运行的几个工具组件单独编译一套,然后根据浏览器入口加载不同的 JS。在开发阶段,则通过 swc-loader 提供兼容性代码。

    重构工具链的过程也挺费时,现有构建工具链实在是反人类。不过最终还是完成了,真正使得这次尝试又失败的原因是 SWC 本身的 bug。几个无法 work around 的 bug 导致我只能放弃这个方案。

    详见:初试 SWC(Speedy Web Compiler)

    不过,SWC 最新版本已经修好了我提交的 bug,大家有机会试试吧。

    6. 用 babel 在编译时生成 IE11 代码

    最后回到 babel+babel-loader。为了体积考虑,我决定继续使用 babel@6。

    然后我发现,目前的代码架构实在是,哎……相信看过 Git 操作特定分支的小技巧 一文的同学都明白我在痛苦什么。

    所以又跟项目结构搏斗许久,终于基本完成了这次重构。

    7. 结果

    这次重构达成了几个目的:

    1. 移除了全量 babel-polyfill,只有 IE11 继续加载
    2. 大部分模块用 ES5 构建,但是不加载 polyfill
    3. 少数模块,不需要兼容 IE11 的使用 ES6 构建

    具体数字没机会统计,就不列了。

    (更多…)
  • 初试 SWC(Speedy Web Compiler)

    初试 SWC(Speedy Web Compiler)

    SWC 是一个用 Rust 写的编译工具,功能跟 babel 很类似。它的优势在于速度,按照官网所说,在单核上它的速度是 babel 的 20倍,四核上是 babel 的 70 倍。

    我最近尝试升级工具链,第一步是使用 esbuild-loader 替代 babel-loader,比较顺利。但是 esbuild 只支持 ES2015,为了支持 IE11,我们还需要再转译一次。这次我想试试 SWC。

    安装与配置

    安装 swc 很简单。我打算 build 的时候用 @swc/cli 转译;debug IE11 的时候把 swc-loader 套在 esbuild-loader 前面输出。所以需要安装三个包:

    nom i @swc/core @swc/cli swc-loader -D

    接下来添加配置文件 .swcrc

    {
      "sourceMaps": false,
      "module": {
        "type": "umd"
      },
      "minify": true
    }

    默认目标平台 target: 'es5',不需要再写。其它语言选项也走默认即可。

    SWC sourceMap 支持三种配置:truefalseinline,意思一看就明白。但目前 bug 比较多,即使设置 sourceMap:false,也只是不生成 sourcemap 文件,对应的链接标记仍然会生成。

    module.type 有另一个 bug:即使目标平台是 ES5,它也会使用 ESM 引入依赖,导致语法解析出错。比如代码中使用了 async function,SWC 转译时就需要 import regeneratorRuntime from 'regenerator-runtime'。所以上面我配置 module.type"umd",一方面避免错误的 ESM import,另一方面可以通过全局方式引用这些库。

    minify: true 表示我们希望 SWC 转译代码时顺便把它们压缩一下。官方文档说这个功能还不是很完善,不过我暂时没发现明显的问题。

    swc 游乐场

    SWC 官方提供预览网站:SWC Playground – SWC。我们可以把源码贴上去,查看编译结果。也可以调整选项,看看不同选项对结果的影响。

    问题

    把 SWC 放进工具链的过程还算顺利,不过接下来使用的时候却遭遇了不少问题。

    首先就是上文说的 ESM 导入的问题。默认情况下 SWC 会 import 'regenerator-runtime',这个问题必须解决。考虑到这个代码特征比较明显,起初,我打算直接字符串过滤掉。后来翻了文档,又在 playground 里尝试了一下,发现 UMD 应该可以解决问题。

    然后是语法问题。下面这段代码 SWC 编译错误:

    // 输入
    let a = 10;
    for (let b = 0; b < a; b++) {
        let c = 0, b = 10, d = 100;
        console.log(b);
    }
    
    // 输出
    var a = 10;
    for (var b = 0; b < a; b++) {
        var c = 0, b = 10, d = 100;
        console.log(b);
    }

    这段代码其实有点意思,我看了很久才找到问题:let 声明变量时,for () 相对于下面的代码块,是上级 context;而 var 时,它们处于同级 context。所以下面这段循环只会运行一次,而不是像上面一样,执行 10 次。

    (这段代码很能考察 letvar 的不同,我准备把它加入我的面试题库。)

    还有其它一些语法问题,因为上面这个问题无法绕过,意味着使用 SWC 这条路不可行,所以我也没有深入研究,就不一一列举了。

    总结

    SWC 用户量太小,未知 Bug 很多;开发团队不大,又是用 Rust 写的,也给想贡献代码的前端社区带来很大阻碍。所以目前还难以应对大型项目、工业级别的需求。

    不过它的速度的确很快,对改进项目构建速度有很大帮助。希望那些 bug 能尽快修复,我们可以早点把它应用到产品当中。

  • FlashDevelop 使用笔记

    Flash Develop是一款非常好用的ActionScript开发工具,其代码提示功能尤为强大;内建各种插件,可以方便的开发、调试、发布;而且还是免费的。最大的缺点可能是不支持ftp,插件相比Eclipse还是要少一些。

    我在使用的版本:4.0.1
    官网地址:http://www.flashdevelop.org/wikidocs/index.php?title=Main_Page
    下载地址:http://www.flashdevelop.org/community/viewtopic.php?f=11&t=8622

    包括Flash Develop使用中遇到的疑似bug、快捷键记录、小技巧、插件推荐等。根据经验实时更新。

    (更多…)