评论

webpack打包优化 swc-loader

swc-loader替代babel-loader, 提升构建速度

1. 前言

大型webpack项目(例如页面300+,组件1k+), 本地开发、上线build,编译耗时太久的问题会影响我们的开发效率、开发体验。通过打包耗时分析,具体原因是webpack配置的各项loader,其中babel-loader占了80%的耗时时间, babel-loader我们做了ts、react、es6等各种的语法转换。针对分析的结果,在现有webpack打包的配置情况下,替换babel-loader的解决方案: swc-loader


2. 调研

2.1 swc介绍

受限于JS的语言本身效率的问题,近几年前端领域出现了不少工具被Rust重写,其中就包括编译JS/TS文件速度比Babel快不少的SWC,其所对标的工具就是BabelSWC全称为Speed Web Compiler,其是基于Rust实现的工具,目前被很多前端知名项目(Next.js、Parcel和Deno)所使用。官方SWC的编译速度相对于Babel可提升近20倍。

swc的详细介绍可参考:https://zhuanlan.zhihu.com/p/437529362


2.2 功能对比

swc-loader vs bable-loader

swc官方对比链接: https://swc.rs/docs/migrating-from-babel

下图是部分功能对比, 通过完整的功能对比, swc-loader可覆盖常用babel-loader插件功能,覆盖总插件80%


通过以上的调研分析,swc-loader替换babel-loader的方案是可行的,且编译效率能得到很大的提升


3. 项目改造

3.1 增加依赖包

@swc/core;@swc/helpers;swc-loader

3.2 打包配置修改

去除之前的babel-loader

替换新的swc-loader配置, 核心代码如下(ts、js类型单独配置: swc的解析配置是区分这两种文件类型,没发合到一起

const { getTsSwcOptions, getJSSwcOptions } = require("./webpack.swcrc.js");
const swcLoader = "swc-loader";
[
      {
        test: /.(ts|tsx)$/,
        use: [
          {
            loader: swcLoader,
            options: getTsSwcOptions(isDebug, isClient),
          },
        ],
      },
      {
        test: /.(js|jsx|mjs|cjs)$/,
        use: [
          {
            loader: swcLoader,
            options: getJSSwcOptions(isDebug, isClient),
          },
        ],
      },
    ];


webpack.swcrc.js 配置如下图

/* eslint-disable no-unused-vars */
// const pkg = require("../package.json");
const getCommon = (isDev = false, isClient = false) => {
  const opt = {
    jsc: {
      // externalHelpers: true,
      transform: {
        legacyDecorator: true,
        decoratorMetadata: true,
        react: {
          runtime: "automatic", // or classic
          throwIfNamespace: true,
          useBuiltins: true,
          development: isDev,
        },
      },
      loose: true,
      parser: {
        decorators: true,
        dynamicImport: true,
      },
      target: "es5",
    },
  };
  // 禁止服务端拆分成chunks
  if (!isClient) {
    opt.module = {
      type: "commonjs",
      // ignoreDynamic: true,
    };
  }
  // 非本地开发
  if (!isDev) {
    opt.env = {
      mode: "entry",
      coreJs: 3,
      forceAllTransforms: true,
      dynamicImport: true,
      // targets: {
      //  ...(isClient
      //    ? { browsers: pkg.browserslist }
      //    : { node: pkg.engines.node.match(/(\d+\.?)+/)[0] }),
      // },
    };
  }
  return opt;
};
const getTsSwcOptions = (isDev = false, isClient = false) => {
  const com = getCommon(isDev, isClient);
  return {
    // test: ".(ts|tsx)$",
    ...com,
    jsc: {
      ...com.jsc,
      parser: {
        ...com.jsc.parser,
        syntax: "typescript",
        tsx: true,
      },
    },
  };
};
const getJSSwcOptions = (isDev = false, isClient = false) => {
  const com = getCommon(isDev, isClient);
  return {
    // test: ".(js|jsx|mjs|cjs)$",
    ...com,
    jsc: {
      ...com.jsc,
      parser: {
        ...com.jsc.parser,
        syntax: "ecmascript",
        jsx: true,
      },
    },
  };
};
module.exports = {
  getTsSwcOptions,
  getJSSwcOptions,
};


4. 最终效果

测试项目信息: webpack5+; 页面100+; 组件400+

window: DELL i7、16G

Mac: MacBook Pro (15-inch, 2018)

5. 总结

本地启动、热更新都有很明显的效率提升

启动编译效率提升最大

window比mac提升效率更高一些


最后一次编辑于  2022-12-24  
点赞 2
收藏
评论

1 个评论

  • 阿白
    阿白
    06-12

    支持了吗

    06-12
    赞同
    回复
登录 后发表内容