You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让NextJS API路由直接输出未打包的原生JavaScript文件?

问题描述

我需要在Next.js构建的网站中创建一个路由,用于输出可在其他网站中使用的JavaScript代码。我在pages/api目录下创建了sendTest.ts文件,同目录下还有一个test.ts文件,希望通过sendTest.ts输出该文件内容。

现有代码

sendTest.ts

import type { NextApiRequest, NextApiResponse } from 'next'
import fs from 'fs';
import path from 'path'

const filePath = path.join(__dirname, 'test.js');
const file = fs.readFileSync(filePath);

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  res.setHeader('Content-Type', 'text/javascript');
  res.status(200).send(file)
}

test.ts

console.log('hello');

问题现象

Next.js构建后,该文件可通过website.com/api/sendTest访问,但打包后的内容包含Webpack相关代码:

"use strict";
(() => {
var exports = {};
exports.id = 318;
exports.ids = [318];
exports.modules = {

/***/ 211:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
console.log("hello there");



/***/ })

};
;

// load runtime
var __webpack_require__ = require("../../webpack-api-runtime.js");
__webpack_require__.C(exports);
var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
var __webpack_exports__ = (__webpack_exec__(211));
module.exports = __webpack_exports__;

})();

当在其他页面通过<script src="website.com/api/sendTest"></script>引入时,会出现错误:

Uncaught ReferenceError: require is not defined
at sendTest:22:27
at sendTest:28:3

我的问题是:如何让NextJS跳过对该文件的Webpack打包,仅将TypeScript转换为JavaScript后原样输出?或者有没有更优的方案来实现从指定NextJS路由输出JavaScript的需求?


解决方案

方案一:静态文件直接访问(最优解)

这是最简单高效的方式,完全绕开Webpack打包:

  • 手动编译test.ts为纯JavaScript:执行tsc test.ts命令,生成test.js文件
  • 将编译后的test.js放到Next.js项目的public目录下
  • 其他网站直接通过<script src="你的域名/test.js"></script>引入即可

这种方式输出的是纯原生JS代码,没有任何额外包装,性能最优。

方案二:API路由动态编译TS为纯JS

如果需要动态生成或实时编译TS文件,可以在API路由中用typescript库直接编译:

  1. 安装依赖:
npm install typescript @types/typescript --save
  1. 修改sendTest.ts代码:
import type { NextApiRequest, NextApiResponse } from 'next'
import fs from 'fs';
import path from 'path'
import * as ts from 'typescript';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const tsFilePath = path.join(__dirname, 'test.ts');
  const tsContent = fs.readFileSync(tsFilePath, 'utf8');

  // 配置编译选项,生成无模块包装的纯JS
  const compilerOptions: ts.CompilerOptions = {
    target: ts.ScriptTarget.ESNext,
    module: ts.ModuleKind.None, // 禁用模块包装
    noEmitOnError: true,
  };

  // 编译TS为纯JS
  const compileResult = ts.transpileModule(tsContent, { compilerOptions });

  res.setHeader('Content-Type', 'text/javascript');
  res.status(200).send(compileResult.outputText);
}

编译后输出的就是纯console.log('hello');代码,没有Webpack的包裹内容。

方案三:配置Webpack跳过特定文件打包

通过修改next.config.js,让Webpack直接读取文件原始内容,不进行打包处理:

  1. 安装依赖:
npm install raw-loader --save-dev
  1. 修改next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config) => {
    // 对test.ts文件使用raw-loader,直接读取原始内容
    config.module.rules.push({
      test: /test\.ts$/,
      use: 'raw-loader',
    });
    return config;
  },
};

module.exports = nextConfig;
  1. 更新sendTest.ts:
import type { NextApiRequest, NextApiResponse } from 'next'
import testRawContent from './test.ts';
import * as ts from 'typescript';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  // 把读取到的TS原始内容编译为纯JS
  const compileResult = ts.transpileModule(testRawContent, {
    compilerOptions: {
      target: ts.ScriptTarget.ESNext,
      module: ts.ModuleKind.None,
    },
  });

  res.setHeader('Content-Type', 'text/javascript');
  res.status(200).send(compileResult.outputText);
}

内容的提问来源于stack exchange,提问作者Neidd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:45:31