如何让非模块JS兼容ES6模块?大型代码库平滑迁移需求
让旧版非模块JS兼容ES6模块的方案
你之前的代码仅添加了CommonJS格式的导出,而浏览器原生ES模块系统只识别export语句,因此会出现导出不存在的错误。以下是无需额外间接层的修改方案,可同时兼容ES6模块、CommonJS和全局变量环境,满足平滑过渡需求:
方案一:直接添加多环境兼容导出
修改原my-api.js,在代码末尾补充不同环境的导出逻辑:
// my-api.js function MyAPI() { this.classVar = null } MyAPI.prototype.myFunction = function() { this.classVar = {something: 3} } // 兼容CommonJS环境(如Node.js、Webpack旧版本) if (typeof module !== 'undefined' && module.exports) { module.exports = MyAPI; } // 兼容ES6模块环境(浏览器原生import、现代打包工具) export default MyAPI; export { MyAPI }; // 兼容非模块全局环境(直接通过script标签引用) if (typeof window !== 'undefined') { window.MyAPI = MyAPI; }
使用方式
- ES6模块导入(支持两种写法):
// 默认导入 import MyAPI from '/static/my-api.js'; // 命名导入 import { MyAPI } from '/static/my-api.js'; - CommonJS环境导入:
const MyAPI = require('./my-api.js'); - 非模块环境:直接通过
window.MyAPI访问构造函数
方案二:UMD风格封装(支持AMD环境)
如果需要同时兼容AMD环境(如RequireJS),可以用IIFE封装代码,同时保留ES模块导出:
// my-api.js const MyAPI = (function(global) { function MyAPI() { this.classVar = null } MyAPI.prototype.myFunction = function() { this.classVar = {something: 3} } // 适配AMD环境 if (typeof define === 'function' && define.amd) { define([], function() { return MyAPI; }); } return MyAPI; })(typeof globalThis !== 'undefined' ? globalThis : window || self); // 兼容CommonJS if (typeof module !== 'undefined' && module.exports) { module.exports = MyAPI; } // 兼容ES6模块 export default MyAPI; export { MyAPI }; // 挂载全局变量 if (typeof window !== 'undefined') { window.MyAPI = MyAPI; }
关键说明
- 浏览器原生ES模块仅识别文件中的
export语句,因此必须添加export default或export { MyAPI }才能被import正确识别。 - 上述方案无需额外中间文件,直接修改原代码即可实现多环境兼容,完美适配新旧代码共存的平滑过渡场景。
内容的提问来源于stack exchange,提问作者Rémi Desgrange
相关产品推荐
相关产品推荐

