如何在Rails项目中通过yarn导入date-fns并解决各类导入报错
第一种导入方式(Webpacker入口导入)的问题根源
你在app/javascript/packs/application.js里写的import format from "date-fns/format";语法本身没有错误,Webpacker也能正常完成date-fns的打包流程。
触发format is not defined报错的核心原因是:
- Webpack 默认对所有导入的模块做严格的作用域隔离,你在入口文件里import的变量,只会存在于打包后的模块闭包内部,不会自动挂载到浏览器全局的
window对象上 - 你在浏览器控制台直接输入
format(...)时,访问的是全局作用域下的变量,自然找不到被封装在模块闭包里的format方法,这个报错本质上不是导入失败,是对Webpack的模块隔离机制理解有偏差。
第二种导入方式(资产管道Sprockets导入)的问题根源
你在app/assets/javascripts/application.js里用//= require date-fns/format的写法,直接触发了两层不兼容问题:
- Sprockets 本质是静态文件拼接工具,只会按顺序把要求的js文件拼接到一起,不具备ES/CommonJS模块的语法转换能力
- date-fns的npm包源码是带CommonJS导出逻辑的,文件开头会包含
Object.defineProperty(exports, "__esModule", ...)、exports.default = format这类CommonJS规范的代码,浏览器原生环境根本不认这种语法,运行到exports代码时找不到对应全局变量,才会触发Uncaught ReferenceError: exports is not defined的报错,后续连锁导致无法获取default导出的format方法,触发第二个类型错误。
简单来说,直接让Sprockets拉取node_modules里的npm包源码是完全错误的使用方式,Sprockets从来就不负责处理npm包的模块兼容。
正确的配置使用方式
你本来通过yarn安装包走Webpacker流程的方向是对的,完全不需要切回资产管道的导入方式,按下面的步骤调整即可:
- 保留你在
app/javascript/packs/application.js里的正确导入语句import format from "date-fns/format"; - 日常业务开发时,直接在
app/javascript目录下的业务js文件里导入format方法使用即可,不需要刻意在浏览器全局控制台直接调用——如果你开发调试阶段确实需要在控制台快速验证方法可用性,可以手动把方法暴露到全局作用域:
配置完成后再回到浏览器控制台调用format方法,就不会出现未定义的报错了。import format from "date-fns/format"; // 仅用于本地调试,上线前可以移除 window.format = format; - 如果你的项目里还有写在
app/assets/javascripts目录下的老脚本,需要用到format方法,直接调用之前手动挂在window上的全局方法即可,不要通过Sprockets的//= require指令直接引用node_modules里的date-fns包文件。 - 补充适配注意点:如果按上述配置导入仍报错,可以检查下安装的date-fns版本,v2版本使用
import format from "date-fns/format"的单函数导入路径是正确的,v3版本之后单函数的导入路径有调整,可根据版本换成import { format } from 'date-fns'的写法即可。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

