JavaScript模块化通过统一ESM语法、条件导出、运行时判断+动态导入、构建时环境标识及抽象接口封装,实现跨平台代码复用与适配。

JavaScript模块化本身不直接解决跨平台问题,但它是实现跨平台代码复用和环境适配的关键基础。核心在于:统一模块语法(如ESM),配合运行时判断 + 条件导出 + 构建工具配置,让同一套源码能按需输出不同平台的产物。
用条件导出(exports)区分平台入口
在package.json中通过exports字段为不同环境指定入口文件,Node.js 12.20+ 和现代打包工具(Vite、Webpack 5+)均支持:
- "import" 对应 ESM 浏览器或 Node ESM 环境
- "require" 对应 CommonJS(如旧版 Node 或某些 SSR 场景)
- "browser" 或自定义条件(如"react-native")可配合打包工具识别
示例:
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"browser": "./dist/index.browser.mjs",
"react-native": "./dist/index.rn.mjs"
}
}
运行时平台检测 + 动态导入按需加载
避免在顶层直接引入平台专属模块(如fs或react-native的AsyncStorage),改用运行时判断 + dynamic import():
- 用typeof window、process?.platform、global?.navigator?.product === 'ReactNative'等轻量判断
- 将平台相关逻辑封装成独立模块(如storage.web.ts、storage.rn.ts),再按需加载
- 注意:动态导入返回 Promise,需 await 或 .then();构建工具通常能自动分包
构建时环境标识 + 类型隔离
利用构建工具注入平台标识,配合 TypeScript 类型守卫提升安全性:
- Vite 中通过define传入__PLATFORM__ = 'web',并在代码中用if (__PLATFORM__ === 'rn')做编译期排除(实际仍需运行时兜底)
- TypeScript 中为不同平台定义专属类型(如StorageDriver接口),各平台实现类分别导入,避免类型冲突
- 使用declare module为平台专属包(如@react-native-async-storage/async-storage)补全类型,防止 TS 报错
统一模块接口 + 抽象层封装
真正降低跨平台耦合度的方式,是设计与平台无关的抽象模块接口:
- 定义清晰的 API 合约(如Storage.save(key, value)、Network.request(url))
- 每个平台提供符合该合约的具体实现(WebStorage、RNStorage),由工厂函数或 DI 容器在启动时注入
- 业务代码只依赖抽象接口,不感知底层差异;测试也只需 mock 接口,无需真实平台环境
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











