TypeScript模块导出与导入报错:浏览器环境下exports未定义问题排查
解决TypeScript转译后浏览器中
exports is not defined错误 问题描述
我尝试在TypeScript中导出一个简单类,相关代码如下:
functions.ts
export class components{ private m_name:string; private m_level:string; constructor(name:string,level:string){ this.m_name=name; this.m_level=level; } }
app.ts
import {components} from './functions'; let c1 = new components("Tushar","Admin");
index.html
<!DOCTYPE html> <html> <head> <title> Feedback </title> </head> <body> <script src= "app.js"></script> </body> </html>
我的tsconfig.json配置:
{ "compilerOptions": { "target": "es5", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } }
运行后浏览器控制台报错:Uncaught ReferenceError: exports is not defined at app.js:2。我试过把target改成es6也没用,但代码在repl.it上能正常运行,请问怎么解决?
原因分析
本质问题在于浏览器原生不支持CommonJS模块系统:你在tsconfig.json里把module设为了commonjs,TypeScript会把代码转译成Node.js环境下的模块格式(依赖exports/require这些全局变量),但浏览器里根本没有这些变量,所以直接引入转译后的app.js就会报错。
repl.it能正常运行是因为它是在Node.js环境下执行代码的,和浏览器的运行环境完全不同。
解决方案
方法1:改用浏览器原生支持的ES Modules
这是最简单的无工具方案,只需要调整配置和HTML标签:
- 更新
tsconfig.json的编译选项,把module改成ESNext(或ES6),同时可以把target设为es6以获得更好的兼容性:
{ "compilerOptions": { "target": "es6", "module": "ESNext", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } }
- 修改index.html中的script标签,加上
type="module"属性,告诉浏览器这是ES模块:
<script type="module" src="app.js"></script>
⚠️ 注意:这种方式需要在本地服务器环境下运行(比如用npx serve启动一个简单服务器),直接双击打开本地HTML文件会触发跨域错误。
方法2:用打包工具(Webpack/Vite)打包代码
如果你的项目后续会更复杂,推荐用打包工具把所有模块打包成浏览器能直接运行的单文件,这也是前端项目的标准做法:
以Webpack为例:
- 初始化项目并安装依赖:
npm init -y npm install webpack webpack-cli ts-loader typescript --save-dev
- 创建
webpack.config.js配置文件:
module.exports = { entry: './app.ts', // 入口文件 module: { rules: [ { test: /\.tsx?$/, // 匹配所有.ts/.tsx文件 use: 'ts-loader', // 用ts-loader处理TypeScript exclude: /node_modules/, }, ], }, resolve: { extensions: ['.tsx', '.ts', '.js'], // 自动解析这些后缀的文件 }, output: { filename: 'bundle.js', // 打包后的文件名 path: __dirname + '/dist', // 输出目录 }, };
- 运行打包命令:
npx webpack --mode development
- 在index.html里引入打包后的文件:
<script src="dist/bundle.js"></script>
方法3:用Browserify转换CommonJS模块
如果暂时不想改模块格式,可以用Browserify把CommonJS模块转换成浏览器能识别的代码:
- 安装依赖:
npm install browserify tsify --save-dev
- 运行转换命令:
browserify app.ts -p [tsify] -o bundle.js
- 在index.html里引入生成的
bundle.js即可。
内容的提问来源于stack exchange,提问作者user14186428
相关产品推荐
相关产品推荐

