#Turbopack with custom webpack loader

1 messages · Page 1 of 1 (latest)

grizzled delta
#

I want to create a custom webpack loader but I can't find how to make it working with Turbopack.

Here's my working next.config.ts:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  turbopack: {
    rules: {
      "*.tsx": {
        loaders: [{ loader: "next-public", options: { shouldLog: true, autoDetect: true } }],
        as: "*.js",
      },
    },
  },
};

export default nextConfig;

But if I do something like :

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  output: "export",
  /* config options here */
  turbopack: {
    rules: {
      "*.ts": {
        loaders: [{ loader: "next-public", options: { shouldLog: true, autoDetect: true } }],
        as: "*.js",
      },
    },
  },
};

export default nextConfig;

It's not working properly, I can't get log from the loader

modest emberBOT
#

Hi @grizzled delta. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Short answer: Turbopack only runs webpack loaders for files it hands to the loader as JavaScript, and its loader API coverage is partial. You need to ensure Turbopack is resolving .ts files through your rule and emitting JS from the loader.

A few checks based on the docs and issues:

  • Your rule shape is correct: map a glob to loaders and cast the output to JS with as: '*.js' (this is required so Turbopack treats the transformed result as JavaScript) (Configuring webpack loaders).
    Example (matches your .tsx case):

    module.exports = {
      turbopack: {
        rules: {
          '*.svg': { loaders: ['@svgr/webpack'], as: '*.js' },
        },
      },
    }
    

    (Examples)

  • Only loaders that return JavaScript are supported; loaders that output non-JS (e.g. stylesheets, images) won’t run under Turbopack (limitations).

  • If resolution is the problem (i.e., Turbopack might not be matching .ts the way you expect), add .ts to resolveExtensions so .ts files are considered in module resolution order:

    module.exports = {
      turbopack: {
        resolveExtensions: ['.mdx', '.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'],
      },
    }
    

    This overwrites the defaults, so include the defaults as shown (Resolving custom extensions, Pages docs variant).

#

Given your .tsx rule works but .ts doesn’t:

  • Ensure imports actually resolve to .ts files (not .tsx or .d.ts). Consider enabling resolveExtensions explicitly as above.
  • Keep as: '*.js' in place.
  • Verify your loader returns JS for .ts inputs.
  • If it still doesn’t trigger, it may be a limitation with Turbopack’s loader integration; the docs note only a core subset is implemented, and options must be plain values (loader limitations).

If you can share a minimal repro, you can compare with the working SVG example structure in the docs to isolate whether it’s resolution or API support.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@grizzled delta Kapa.ai is still learning and improving, please let me know how I did by reacting below.

grizzled delta
#

Can I compile Typescript files that are inside a specific directory?

#

@modest ember Can I compile Typescript files that are inside a specific directory?

modest emberBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Short answer: Not directly via a “compile only this directory” switch. Turbopack compiles files that are part of your module graph and within the project root. You can influence what’s considered by:

If your goal is to run a custom loader only for .ts in a specific directory, you can target that pattern in turbopack.rules (and ensure the loader outputs JS via as: '*.js'):

module.exports = {
  turbopack: {
    rules: {
      'src/special/**/*.ts': {
        loaders: ['your-loader'],
        as: '*.js',
      },
    },
  },
}

Loaders are limited to ones that return JavaScript, and only a core subset of the webpack loader API is supported (Configuring webpack loaders and limitations).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@grizzled delta Kapa.ai is still learning and improving, please let me know how I did by reacting below.

grizzled delta
#

@modest ember How does files are selected? If I never import a file, will it be passed in turbopakc?

modest emberBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Files are included only if they’re part of the module graph requested by the dev server. Turbopack does “lazy bundling” in dev: it bundles what’s actually requested, not everything under your project root. So if a file is never imported (directly or indirectly) from an entry it won’t be processed by Turbopack. (This is distinct from root-scoping: files outside the configured root aren’t resolved at all.) (Why Turbopack? → Lazy Bundling, Root directory behavior)

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@grizzled delta Kapa.ai is still learning and improving, please let me know how I did by reacting below.

grizzled delta
#

@modest ember which loader can I use to have a system like this :

importing a TypeScript file with a specific extension like "xxx.ts", the import returns an object with "url" inside like for images

modest emberBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

I’m sorry, but the knowledge sources don’t mention a Turbopack-supported loader that turns TypeScript imports into “URL-returning” assets (like images). Turbopack’s loader support is limited to loaders that return JavaScript, and examples focus on things like @svgr/webpack; there’s no documented “asset/resource”-style loader for TS files, nor guidance to emit a URL object from a TS import (Configuring webpack loaders and limitations, Supported loaders).

For assets, a common pattern is using new URL('file.ext', import.meta.url), which Turbopack supports to generate an asset URL for static files (not TS source), but this isn’t documented for transforming TS files themselves (related discussion showing new URL works for assets).

If you still want to try a custom rule, you could target a glob and cast to JS, but your loader would need to return JS code that exports a URL string/object, and it must only use the subset of webpack loader APIs supported by Turbopack:

module.exports = {
  turbopack: {
    rules: {
      '*.xxx.ts': {
        loaders: ['your-loader'],
        as: '*.js',
      },
    },
  },
}

However, the docs do not confirm such a loader exists or that this pattern is officially supported for TS files (Configuring webpack loaders).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: