JavaScript模块化处理前后端共用模块的核心是分层设计与环境适配,真正可共用的仅三类:纯逻辑工具函数、TypeScript类型定义、配置常量;需规避环境特有API,通过构建时注入、运行时判断和统一ESM语法实现安全复用。

JavaScript模块化处理前后端共用模块的环境适配,核心不是“让同一份代码无修改地跑两边”,而是通过分层设计、环境感知和构建介入,把逻辑拆解为可复用的部分与必须隔离的部分。
明确哪些能共用,哪些必须隔离
真正适合共用的只有三类内容:
-
纯逻辑工具函数:如日期格式化、字符串截断、基础校验等,不依赖任何全局对象或 I/O;需确保不调用
document、localStorage、fs、fetch等环境特有 API -
TypeScript 类型定义:接口、联合类型、泛型工具类型(如
ApiResponse<T>)可被前后端同时引用,零运行时开销 -
配置常量与业务规则:如错误码映射表、API 路径前缀、枚举值等;但注意前端需在构建时注入(如 Webpack DefinePlugin 或 Vite define),后端走
process.env或 JSON 配置文件
用运行时判断隔离环境特有逻辑
当某段逻辑确实需要跨环境存在(比如初始化埋点、日志上报),不能硬编码 window.xxx 或 global.xxx,而应主动检测:
- 判断执行环境:
typeof window !== 'undefined'表示浏览器,typeof process === 'object' && process?.versions?.node表示 Node.js - 将 DOM 操作、事件监听、样式注入等推迟到组件挂载阶段(如 React 的
useEffect(() => {}, [])) - 第三方库按需引入:服务端用
axios,浏览器端用fetch封装;可用动态import()加载仅限某环境的模块
统一模块语法,交由构建工具处理差异
源码层优先采用 ES Module(import/export),避免混用 CommonJS:
立即学习“Java免费学习笔记(深入)”;
- Node.js 项目可通过
"type": "module"在package.json中启用原生 ESM,或使用.mjs后缀 - 构建工具(Vite/Webpack/Rollup)会自动将 ESM 转为兼容目标环境的输出,包括处理
require兼容、polyfill 注入、环境变量替换 - 避免在共用模块中写
module.exports或require,尤其不要在 ESM 文件里混用 CommonJS 导出
封装跨平台请求与状态管理入口
数据获取是前后端差异最集中的环节,需抽象一层:
- 定义统一请求函数签名,内部根据环境选择实现:
fetch(浏览器)、node-fetch或axios(Node.js) - SSR 场景下,服务端预取数据时禁用 cookie、localStorage 等客户端专属状态,确保请求可复现且无副作用
- 状态初始化逻辑分离:服务端传入初始数据(
window.__INITIAL_DATA__或 SSR context 注入),客户端只负责 hydrate,不重复拉取


















