为何nodemon可运行index.ts,node与ts-node却无法运行?
为什么nodemon能运行TS服务端文件,而node/ts-node不行?
我正在开发一个基于TypeScript、React、Express、Node、Webpack和Babel的项目,卡这个问题好几天了:
- 用
node src/server/index.ts作为启动脚本时,src/server/index.ts里的import语法会触发SyntaxError: Cannot use import statement outside a module错误 - 换成
nodemon src/server/index.ts作为启动脚本却能正常运行
我试过各种修复,比如在package.json加"type": "module"、修改tsconfig里的target/moduleResolution/module/allowJS等属性,全都没用。最后靠在tsconfig.json里加ts-node专属配置,再换nodemon解决了问题,但搞不懂原理,求解释。
我的配置文件
tsconfig.json
{ "ts-node": { /* 编辑:这些ts-node选项显然非常重要... */ "compilerOptions": { /* 如果移除这些行,即使使用nodemon也会出现最初的错误: */ "module": "commonjs" /* `SyntaxError: Cannot use import statement outside a module` */ } }, "compilerOptions": { "target": "ES5", "module": "ESNext", "moduleResolution": "nodenext", "lib": [ "DOM", "ESNext" ], "jsx": "react-jsx", "noEmit": true, "isolatedModules": true, "esModuleInterop": true, "strict": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "allowJs": true }, "include": [ "src/client/**/*" ] }
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const paths = { DIST: path.resolve(__dirname, 'dist'), SRC_ENTRY: path.resolve(__dirname, 'src', 'client', 'Index.tsx'), HTML_TEMPLATE: path.resolve(__dirname, 'src', 'client', 'index.html'), }; module.exports = { mode: 'development', entry: paths.SRC_ENTRY, resolve: { extensions: ['.tsx', '.ts', '.js'], }, output: { filename: 'bundle.js', path: paths.DIST, }, module: { rules: [ { test: /\.(ts|js)x?$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, ], }, plugins: [ new HtmlWebpackPlugin({ template: paths.HTML_TEMPLATE }), new ForkTsCheckerWebpackPlugin(), ], };
src/server/index.ts
import express, { Express } from 'express'; /* <-- 此处是触发错误的第一个import */ import path from 'path'; export const app: Express = express(); /* ... */
原因解释
1. 直接用node运行肯定报错
Node.js本身不支持直接运行TypeScript文件,也不会自动编译TS代码。而且你的TS里用了import语法,Node默认处于CommonJS模块环境,不认识ES模块的import,所以直接跑必然触发语法错误。
2. ts-node单独运行可能失败的原因
你的tsconfig有两个关键问题:
- 根
compilerOptions里module设为ESNext,这会让ts-node把TS编译成ES模块代码,但Node默认不支持直接运行ES模块(即使加"type": "module"也没用,因为还有另一个问题); include数组只包含了src/client/**/*,没覆盖服务端的src/server文件,ts-node默认会遵循这个配置,可能无法正确处理服务端TS文件的编译规则。
3. nodemon能运行的核心原因
- Nodemon在检测到运行TS文件时,会自动调用
ts-node来编译并运行代码; - 你在tsconfig里专门加了
"ts-node"配置块,里面指定了"module": "commonjs"——ts-node会优先读取这个专属配置,把服务端TS代码编译成Node能识别的CommonJS模块,自然不会再触发import语法错误; - 另外,ts-node在直接运行单个文件时,会忽略
include配置,强制编译目标文件,所以即使你的include没包含server目录,也能正常处理服务端代码。
内容的提问来源于stack exchange,提问作者Colin Brett Williams
相关产品推荐
相关产品推荐

