Expo Android自定义插件使用import报错,如何保留TypeScript优势?
解决Expo自定义插件无法使用ES模块语法的问题
问题背景
开发Expo Android自定义插件时,使用官方示例的import/export语法会触发SyntaxError: Cannot use import statement outside a module错误,改用require虽能运行,但会丢失TypeScript类型支持,降低开发体验。
核心原因
Node.js默认以CommonJS(CJS)模块系统加载文件,import/export属于ES模块(ESM)语法,直接运行会被Node判定为非模块文件,从而抛出语法错误。
解决方案
方案1:用TypeScript编写并编译为CommonJS(推荐)
这是兼顾TypeScript优势和Expo兼容性的最优方案:
- 初始化插件的TypeScript环境
在插件目录执行:npm init -y npm install typescript @types/node @expo/config-plugins --save-dev npx tsc --init - 修改
tsconfig.json关键配置:{ "compilerOptions": { "module": "CommonJS", "target": "ES2018", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } - 在
src目录编写TS插件(示例:修改MainActivity):import { ConfigPlugin, withDangerousMod } from '@expo/config-plugins'; import fs from 'fs'; import path from 'path'; const withCustomMainActivity: ConfigPlugin = (config) => { return withDangerousMod(config, [ 'android', async (config) => { // 替换为你的MainActivity路径 const mainActivityPath = path.join( config.modRequest.platformProjectRoot, 'app', 'src', 'main', 'java', 'com', 'yourcompany', 'yourapp', 'MainActivity.java' ); let content = fs.readFileSync(mainActivityPath, 'utf8'); // 示例:插入自定义代码 if (!content.includes('// Custom injected code')) { content = content.replace( 'super.onCreate(savedInstanceState);', 'super.onCreate(savedInstanceState);\n // Custom injected code' ); fs.writeFileSync(mainActivityPath, content); } return config; }, ]); }; export default withCustomMainActivity; - 在插件的
package.json添加编译脚本:{ "scripts": { "build": "tsc" } } - 执行
npm run build编译,在Expo项目的app.json中引用编译后的文件:{ "expo": { "plugins": ["./path-to-your-plugin/dist/index.js"] } }
方案2:将插件标记为ES模块
无需编译,直接让Node识别插件为ES模块:
- 在插件目录的
package.json中添加:{ "type": "module" } - 注意:所有文件必须统一使用ESM语法,不能混合
require;若需引用CommonJS模块,需用createRequire转换:import { createRequire } from 'module'; const require = createRequire(import.meta.url); // 引用CommonJS模块示例 const cjsModule = require('some-cjs-package'); - 配合TypeScript时,需将
tsconfig.json的module设为ESNext,编译后输出ESM格式。
方案3:使用.mjs扩展名
将插件文件重命名为.mjs(TS文件用.mts),Node会自动将其当作ES模块处理,无需修改package.json。该方式适合小型单文件插件,大型插件管理效率不如TS编译方案。
内容的提问来源于stack exchange,提问作者Vivere
相关产品推荐
相关产品推荐

