Serverless AWS Lambda转TypeScript遇模块外import语句错误
问题:Serverless Lambda迁移TypeScript时出现import语法运行时错误
我正在将Serverless AWS Lambda微服务API迁移至TypeScript,计划保留现有JS文件并逐步新增TS文件。但配置Webpack与TypeScript后,调用getInstitutionInfo Lambda函数时触发以下运行时错误:
× Unhandled exception in handler 'getInstitutionInfo'. × Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module at _loadUserApp (C:\git\my-project\node_modules\serverless-offline\src\lambda\handler-runner\in-process-runner\aws-lambda-ric\UserFunction.js:307:15) at async module.exports.load (C:\git\my-project\node_modules\serverless-offline\src\lambda\handler-runner\in-process-runner\aws-lambda-ric\UserFunction.js:341:21) at async InProcessRunner.run (file:///C:/git/my-project/node_modules/serverless-offline/src/lambda/handler-runner/in-process-runner/InProcessRunner.js:41:21) at async MessagePort.<anonymous> (file:///C:/git/my-project/node_modules/serverless-offline/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js:24:14) × SyntaxError: Cannot use import statement outside a module
怀疑问题出在第三方依赖包而非自身代码,当前使用的tsconfig.json与Webpack配置如下:
tsconfig.json
{ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "lib": [ "es2020" ], "module": "commonjs", "target": "es2020", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "sourceMap": true, "allowJs": true, "outDir": ".erb/dll" } }
Webpack配置文件
const path = require('path'); const slsw = require('serverless-webpack'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const nodeExternals = require('webpack-node-externals'); module.exports = { mode: slsw.lib.webpack.isLocal ? 'development' : 'production', devtool: slsw.lib.webpack.isLocal ? 'source-map' : 'cheap-source-map', entry: slsw.lib.entries, target: 'node', resolve: { extensions: ['.cjs', '.mjs', '.js', '.ts'], }, output: { libraryTarget: 'commonjs2', path: path.join(__dirname, '.webpack'), filename: '[name].js', }, externals: ['aws-sdk', nodeExternals()], module: { rules: [ { test: /\.[jt]s?$/, loader: 'ts-loader', exclude: [ [ /node_modules/, path.resolve(__dirname, '.webpack'), path.resolve(__dirname, '.serverless'), ], ], options: { transpileOnly: true, experimentalFileCaching: true, }, }, ], }, plugins: [new ForkTsCheckerWebpackPlugin()], };
解决方案
1. 处理第三方ES模块依赖
你的Webpack配置使用了nodeExternals(),会将所有node_modules中的依赖排除在打包流程外。如果某个第三方依赖本身是ES模块(使用import/export语法),Node.js会因为Lambda产物是CommonJS格式而无法识别,触发语法错误。
修改externals配置,把有问题的依赖包加入allowlist,让Webpack将其打包并转译为CommonJS:
externals: ['aws-sdk', nodeExternals({ allowlist: ['有问题的第三方包名'] // 替换为实际出问题的包,比如'axios' })],
如果多个包有问题,可以用正则匹配,比如allowlist: /^@your-org\/.+/匹配特定组织的包。
2. 优化TypeScript与Webpack的模块配置
- 给
tsconfig.json添加moduleResolution: 'node',确保模块解析逻辑符合Node.js规范:"compilerOptions": { // ... 原有配置 "moduleResolution": "node" } - 将Webpack的
target设为你Lambda实际使用的Node.js版本(比如Node.js 18),提升兼容性:target: 'node18', // 对应Lambda的Node.js 18.x运行时
3. 确保JS文件被正确转译
虽然你怀疑是第三方包的问题,但仍需确认现有JS文件是否混用了ES模块与CommonJS语法。可以调整Webpack的loader规则,确保JS文件被ts-loader正确处理:
{ test: /\.[jt]s?$/, use: ['ts-loader'], exclude: [/node_modules/, path.resolve(__dirname, '.webpack'), path.resolve(__dirname, '.serverless')], }
4. 调整Serverless Offline配置
在serverless.yml中给serverless-offline添加useChildProcesses: true,避免本地运行时的模块加载冲突:
plugins: - serverless-webpack - serverless-offline custom: serverless-offline: useChildProcesses: true
内容的提问来源于stack exchange,提问作者Real World
相关产品推荐
相关产品推荐

