![Next.jsのSWCコンパイラでPolyfillの自動挿入はできるのか](/_next/image/?url=https%3A%2F%2Fblog-next-posts.vercel.app%2Fassets%2Fposts%2Fnext-swc-auto-polyfill-survey%2Fnext-swc-auto-polyfill-survey.png&w=3840&q=75)
この記事はNext.js@14.2での調査結果になります。
Next.jsでPolyfillを自動挿入できるか
結論から言うと、SWCを使用している場合はPolyfillを自動挿入する設定はありませんでした。
Babelを使用している場合は、設定次第でPolyfillを自動挿入することが可能です。
https://babeljs.io/docs/babel-preset-env#usebuiltins
そもそも、SWCでPolyfillの自動挿入はできる?
純正のSWCでもBabel同様の機能を提供しています。
.swcrcにtargetとmodeを指定すると、トランスパイル結果にPolyfillが挿入されます。
{
"env": {
"targets": "Chrome >= 48, Safari > 9",
"mode": "usage"
}
}
以下のような、新しめのメソッドを使ったコードで試してみます。
const hoge = "hoge"
console.log(hoge.replaceAll("1", "2"))
const arr = [1, 4, 3, 2].toSorted()
トランスパイル後のコードは次のようになります。
npx swc ./index.js
の出力結果:
import "core-js/modules/es.string.replace.js";
import "core-js/modules/es.regexp.exec.js";
import "core-js/modules/es.array.sort.js";
var hoge = "hoge";
console.log(hoge.replaceAll("1", "2"));
var arr = [1, 4, 3, 2].toSorted();
文頭にcore-jsのPolyfillコードが注入されました。
Next.jsでenvの設定ができないのか
Webpackの設定からSWCのオプションであるenvを指定できれば、Polyfillの自動挿入が可能と考えました。
Next.jsのドキュメントにはSWCローダーに関する記載がなかったため、実装の方を調査しました。
next.config.jsの出力結果から探る
next.config.jsからWebpackをカスタマイズできるので、ログを仕込んで確認します。
webpack: (config, options) => {
if (options.isServer) {
return config;
}
console.dir(config.module.rules, { depth: 5 });
return config;
}
出力された結果から、それらしきものを発見しました。
{
test: { or: [/\.(tsx|ts|js|cjs|mjs|jsx)$/, /__barrel_optimize__/] },
include: [
'/myproject/path',
/next[\\/]dist[\\/](esm[\\/])?shared[\\/]lib/,
/next[\\/]dist[\\/](esm[\\/])?client/,
/next[\\/]dist[\\/](esm[\\/])?pages/,
/[\\/](strip-ansi|ansi-regex|styled-jsx)[\\/]/
],
exclude: [Function: exclude],
use: [
{
loader: 'next-swc-loader',
options: {
isServer: false,
rootDir: '/myproject/path',
pagesDir: '/myproject/path/src/pages',
appDir: undefined,
hasReactRefresh: false,
nextConfig: [Object],
jsConfig: [Object],
transpilePackages: [Array],
supportedBrowsers: [Array],
swcCacheDir: '/myproject/path/.next/cache/swc',
serverComponents: true,
esm: false
}
}
]
}
next-swc-loader
がSWCでコードをトランスパイルしてると予想できます。
next-swc-loaderの実装を探す
GitHubからコードを探します。
Webpackのオプションを生成している箇所:
https://github.com/vercel/next.js/blob/v14.2.3/packages/next/src/build/webpack-config.ts#L426
next-swc-loader:
https://github.com/vercel/next.js/blob/v14.2.3/packages/next/src/build/webpack/loaders/next-swc-loader.ts
SWCオプションに変換している箇所:
https://github.com/vercel/next.js/blob/v14.2.3/packages/next/src/build/webpack/loaders/next-swc-loader.ts#L115
getLoaderSWCOptions:
https://github.com/vercel/next.js/blob/v14.2.3/packages/next/src/build/swc/options.ts#L324
next.config.jsから設定できるオプションをSWCオプションに置換している箇所まで辿り着きました。
https://github.com/vercel/next.js/blob/v14.2.3/packages/next/src/build/swc/options.ts#L454-L474
そして一番重要なenvの部分が以下のように記述されていました。
...(supportedBrowsers && supportedBrowsers.length > 0
? {
env: {
targets: supportedBrowsers
}
}
: {}),
Polyfillを挿入するにはenv.mode
を設定する必要がありますが、追加する余地がありませんでした。
結論
残念ながら、Next.jsのSWCコンパイラではPolyfillの自動挿入を設定することができませんでした。
SWCのオプションを設定したい要望はいくつか上がってるので、いつかできるようになると良いですね。
https://github.com/vercel/next.js/discussions/46979
https://github.com/vercel/next.js/discussions/30413
https://github.com/vercel/next.js/discussions/30940