Skip to content

feat(experimental-extractor): pluggable bundler interface + rolldown support#2572

Merged
andrii-bodnar merged 27 commits into
mainfrom
experimental-extractor-plugable-bundler
Jun 26, 2026
Merged

feat(experimental-extractor): pluggable bundler interface + rolldown support#2572
andrii-bodnar merged 27 commits into
mainfrom
experimental-extractor-plugable-bundler

Conversation

@timofei-iatsenko

@timofei-iatsenko timofei-iatsenko commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Description

This one is made on top of #2571

Summary

  • Makes the bundler for extract-experimental configurable via the bundler field in experimental.extractor config
  • Adds createEsbuildBundler() and createRolldownBundler() factory functions as separate entrypoints (@lingui/cli/bundlers/esbuild, @lingui/cli/bundlers/rolldown)
  • enables codesplitting for esbuild bundlers, and implement a traversal of emitted common chunks in the extractor (should improve speed a lot!)
  • Deprecates includeDeps, excludeExtensions, and resolveEsbuildOption on the extractor config in favor of passing them to the bundler factory
  • improve cli command logging output, not it logs phases (bundling, extracting, writing) and show some additional errors.
  • respect corePackage/jsxPackage setting
  • makes rolldown and esbuild optional dependencies

Motivation

The experimental extractor was hardcoded to esbuild. Users who prefer rolldown (or another bundler) had no way to swap it. The new ExperimentalExtractorBundler interface is minimal — bundle(entryPoints, outDir, linguiConfig) => BundleResult — so custom implementations are straightforward.

Usage

  // lingui.config.ts
  import { createRolldownBundler } from "@lingui/cli/bundlers/rolldown"

  export default defineConfig({
    experimental: {
      extractor: {
        entries: ["src/**/*.page.tsx"],
        output: "src/locales/{entryName}.{locale}",
        bundler: createRolldownBundler(),
      },
    },
  })

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Examples update

Fixes # (issue)

Checklist

  • I have read the CONTRIBUTING and CODE_OF_CONDUCT docs
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)

@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
js-lingui Ready Ready Preview Jun 22, 2026 8:15am

Request Review

@timofei-iatsenko timofei-iatsenko changed the title feat(experimental-extractor): make a bundler configurable, add rolldown feat(experimental-extractor): pluggable bundler interface + rolldown support Jun 11, 2026
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

size-limit report 📦

Path Size
packages/core/dist/index.mjs 1.69 KB (0%)
packages/detect-locale/dist/index.mjs 633 B (0%)
packages/react/dist/index.mjs 1.22 KB (0%)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the extract-experimental pipeline bundler-pluggable by introducing a minimal bundler interface and shipping built-in bundlers for esbuild (default) and rolldown, plus updates the macro extraction mark to a JSDoc-style comment so it survives rolldown output.

Changes:

  • Add ExperimentalExtractorBundler / BundleResult types and a new experimental.extractor.bundler config field (with deprecations for esbuild-specific options on the extractor config).
  • Replace the hardcoded esbuild bundling with a bundler abstraction and add createEsbuildBundler() and createRolldownBundler() implementations.
  • Update macro extraction marks and extraction logic to support both /*i18n*/ and /** i18n */, plus add an E2E rolldown extractor test.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
yarn.lock Adds/updates lock entries for rolldown + plugin-babel and bumps esbuild version.
packages/conf/src/types.ts Introduces BundleResult + ExperimentalExtractorBundler types; adds bundler option and deprecations on extractor config.
packages/conf/src/makeConfig.ts Extends example/validation shape to allow experimental.extractor.bundler.
packages/cli/test/index.test.ts Adds E2E test coverage for experimental extractor using rolldown.
packages/cli/test/extractor-experimental/lingui.config.rolldown.ts Adds test config exercising createRolldownBundler().
packages/cli/src/lingui-extract-experimental.ts Switches extractor to use configured bundler, defaulting to esbuild bundler factory.
packages/cli/src/extract-experimental/linguiEsbuildPlugin.ts Uses a config-aware content filter regex for macro detection.
packages/cli/src/extract-experimental/constants.ts Centralizes the default excluded extensions list.
packages/cli/src/extract-experimental/bundleSource.ts Removes old esbuild-only bundling implementation (superseded by bundlers).
packages/cli/src/extract-experimental/bundlers/rolldown.ts Adds rolldown bundler implementation.
packages/cli/src/extract-experimental/bundlers/esbuild.ts Adds esbuild bundler implementation replacing the old bundling code.
packages/cli/src/extract-experimental/buildContentFilter.ts Adds helper to build macro import detection regex from linguiConfig.macro.
packages/cli/package.json Exposes new bundler entrypoints and changes bundler-related dependency declarations.
packages/babel-plugin-lingui-macro/test/fixtures/jsx-plural-select-nested.expected.js Updates expected output to JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/fixtures/jsx-keep-forced-newlines.expected.js Updates expected output to JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/fixtures/js-t-var/js-t-var.expected.js Updates expected output to JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/fixtures/js-t-continuation-character.expected.js Updates expected output to JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/lingui-directive.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/jsx-trans.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/jsx-selectOrdinal.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/jsx-select.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/jsx-plural.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/jsx-placeholder.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-useLingui.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-t.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-selectOrdinal.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-select.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-plural.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/test/snapshots/js-defineMessage.test.ts.snap Snapshot updates for JSDoc-style extraction mark.
packages/babel-plugin-lingui-macro/src/constants.ts Changes the extraction mark value to produce /** i18n */ output.
packages/babel-plugin-extract-messages/test/extract-messages.test.ts Adds test ensuring both old and new extraction mark formats are supported.
packages/babel-plugin-extract-messages/src/index.ts Updates detection logic to accept both i18n and * i18n comment bodies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/cli/src/extract-experimental/bundlers/esbuild.ts Outdated
Comment thread packages/cli/src/extract-experimental/bundlers/rolldown.ts Outdated
Comment thread packages/cli/package.json
@timofei-iatsenko

This comment was marked as resolved.

@andrii-bodnar

This comment was marked as resolved.

@timofei-iatsenko

This comment was marked as outdated.

@andrii-bodnar andrii-bodnar linked an issue Jun 12, 2026 that may be closed by this pull request

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 40 changed files in this pull request and generated 5 comments.

Files not reviewed (8)
  • packages/cli/test/extractor-experimental/expected-rolldown/about.page.en.js: Generated file
  • packages/cli/test/extractor-experimental/expected-rolldown/about.page.pl.js: Generated file
  • packages/cli/test/extractor-experimental/expected-rolldown/index.page.en.js: Generated file
  • packages/cli/test/extractor-experimental/expected-rolldown/index.page.pl.js: Generated file
  • packages/cli/test/extractor-experimental/expected/about.page.en.js: Generated file
  • packages/cli/test/extractor-experimental/expected/about.page.pl.js: Generated file
  • packages/cli/test/extractor-experimental/expected/index.page.en.js: Generated file
  • packages/cli/test/extractor-experimental/expected/index.page.pl.js: Generated file
Comments suppressed due to low confidence (1)

packages/cli/src/extract-experimental/linguiEsbuildPlugin.ts:27

  • buildContentFilterRe(options.linguiConfig) is recomputed for every loaded file. Since it only depends on the config, it can be computed once in setup and reused, reducing per-file overhead during bundling.
  setup(build) {
    build.onLoad({ filter: babelRe, namespace: "" }, async (args) => {
      const filename = path.relative(process.cwd(), args.path)

      const contents = await fs.promises.readFile(args.path, "utf8")

      const hasMacroRe = buildContentFilterRe(options.linguiConfig)

      if (!hasMacroRe.test(contents)) {
        // let esbuild process file as usual
        return undefined
      }

Comment thread website/docs/guides/message-extraction.md
Comment thread website/docs/guides/message-extraction.md
Comment thread packages/cli/src/extract-experimental/bundlers/rolldown.ts
Comment thread packages/conf/src/types.ts
Comment thread packages/cli/src/extract-experimental/buildChunkGraph.ts
@timofei-iatsenko timofei-iatsenko marked this pull request as ready for review June 16, 2026 10:04
@timofei-iatsenko

Copy link
Copy Markdown
Collaborator Author

@andrii-bodnar anything here to make it merged?

@andrii-bodnar andrii-bodnar merged commit 06940ed into main Jun 26, 2026
11 checks passed
@andrii-bodnar andrii-bodnar deleted the experimental-extractor-plugable-bundler branch June 26, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove required dependency on esbuild

3 participants