PAYATHON 2026

Next.js 如何直接转译含 .js 导入的 TypeScript 共享库?

数据小许

结论

如果 Next.js 开发服务器使用 webpack,可以保留共享库源码中的 .js 导入,并在 webpack 的 resolve.extensionAlias 中配置:遇到 .js 请求时,先查找对应的 .ts 或 .tsx 文件,再查找 .js 文件。transpilePackages 用于转译共享库;扩展名映射则让 ../../trend/SMA/SMA.js 请求匹配到实际的 TypeScript 源文件。

配置示例

在 next.config.ts 中保留 transpilePackages,并添加 webpack 配置:

import type {NextConfig} from 'next';

const nextConfig: NextConfig = {
  experimental: {
    externalDir: true,
  },
  reactStrictMode: true,
  transpilePackages: ['shared-library'],
  output: 'export',
  images: {
    unoptimized: true,
  },
  webpack(config) {
    config.resolve.extensionAlias = {
      ...config.resolve.extensionAlias,
      '.js': ['.ts', '.tsx', '.js'],
    };

    return config;
  },
};

export default nextConfig;

共享库中的 ESM 导入可以继续写成:

import { SMA } from '../../trend/SMA/SMA.js';

webpack 解析这个 .js 请求时,会先查找 SMA.ts 或 SMA.tsx。如果库中有 SMA.js,配置也会继续查找该文件。

如果共享库继续使用 moduleResolution: "node16" 或 "nodenext",应保留符合 ESM 规则的 .js 相对导入。TypeScript 会按相应规则解析源码中的导入;上述 webpack 映射只影响 Next.js 构建时的文件查找,无需删除库源码导入中的扩展名。

检查包解析路径

确认 shared-library 的包入口或应用的 paths 映射指向共享库源码,并检查报错中的相对路径是否能从导入文件所在目录找到对应的 .ts 或 .tsx 文件。transpilePackages 不会自动将源码中的 .js 导入改写为 .ts 导入,所以仅配置它无法解决文件扩展名不匹配的问题。

如果开发服务器使用其他构建器,webpack 配置回调不会处理该构建器的模块解析。此时需要为实际使用的构建器配置等效的扩展名映射;如果无法配置,可以先构建共享库,再让 Next.js 使用构建产物。

备注:内容仅供参考。