我正在将一个较旧的应用程序升级到Rails 6,它使用webpacker
进行所有JS Assets 管理。
我正在使用pikaday
日历库,并已通过yarn add pikaday
添加了它,并验证它是否显示在packages.json
中,然后通过app/javascript/packs/application.js
将其添加到了我的require("pikaday")
中。
我有一个称为Datepicker
的JS类,用于抽象实际的pikaday
日历。之所以这样做,是因为有一天我可能会更改datepicker的实现,并且这种方式只需要更改一个类,而不用更新所有的pikaday
调用即可。
但是,是否在require("pikaday")
包文件中使用application.js
似乎无关紧要;只要我在要引用它的类中使用import Pikaday from "pikaday"
,它就没有区别。
问题
我试图了解正在发生的事情。
require("pikaday")
文件中添加import Pikaday from "pikaday"
或app/javascript/pack/application.js
?为什么或者为什么不? import CLASS from "class_file"
?在我的示例中,我想在多个地方使用Datepicker
类。我问的原因是因为我有10多个这样的类,在每个要使用它们的JS文件的顶部都有10多个import
语句有点令人讨厌。我总是想访问某些类。我已经使用了webpacker ProvidePlugin功能,但是它抱怨Datepicker
不是构造函数,因此我可能缺少了一些东西,但是我没有足够的知识来知道什么。 app / javascript / custom / datepicker.js
import Pikaday from "pikaday"
export default class Datepicker {
constructor(element, options) {
if (options == null) { options = {} }
// Store DOM element for reference
this.element = element
// Do not re-run on elements that already have datepickers
if (this.element.datepicker === undefined) {
options = Object.assign({},
this.defaultOptions(),
options
)
const picker = new Pikaday(options)
// Store picker on element for reference
this.element.datepicker = picker
return picker
} else {
console.log("Datepicker already attached")
return
}
}
// Overridden by `options` in constructor
defaultOptions() {
return {
field: this.element,
format: "M/D/YYYY",
bound: true,
keyboardInput: false,
showDaysInNextAndPreviousMonths: true
}
}
}
app / javascript / packs / application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("moment")
// Note: if using `@rails/ujs`, you do not need to use `jquery-ujs`.
import "jquery"
// Does not matter if I require this or not, as long as it is imported in the
// class file, I can remove this require statement and everything still works.
require("pikaday")
// StimulusJS
// Webpack's `require` looks for `controllers/index.js` by default
require("controllers")
require("custom/datepicker")
最佳答案
您问了几个问题:
import Pikaday from 'pikaday'
的文件中只需要Pikaday
即可。在这种情况下,只需要在自定义datepicker模块中进行此导入。您可以从application.js包文件中删除require("pikaday")
。原因是Webpack将把application.js包作为依赖关系图的入口;从那里开始,它将递归地遍历每个必需/导入的模块,找到那些模块的依赖关系,依此类推,直到 bundle 包中包含所有声明的模块。由于您已经在application.js包中声明了
import 'custom/datepicker'
,并且自定义datepicker导入了pikaday
,它将作为依赖项包含在 bundle 软件中。 Datepicker
,所以您的自定义export default ...
被编译为ES模块(而是Webpack的ES模块的实现)。这对于ProvidePlugin的工作方式很重要。从Webpack 4 documentation of ProvidePlugin
:这意味着您的
Datepicker
插件条目的Webpack配置如下所示(使用Rails Webpacker环境api):const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
const {resolve} = require('path');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
Datepicker: [resolve('app/javascript/custom/datepicker'), 'default']
}))
module.exports = environment
意见:就是说,我鼓励您明确输入,例如在每个模块中引用了
import Datepicker from 'custom/datepicker'
的Datepicker
。即使是重复的,与诸如ESlint之类的工具进行集成也将变得更加容易,该工具可以通过某些代码编辑器提供有关编译错误的内联反馈-更加容易在每个模块中声明的显式依赖项进行设置。 我将您的自定义Datepicker与ProvidePlugin结合在一起使用了Pikaday的工作演示:https://github.com/rossta/rails6-webpacker-demo/commit/be3d20107c2b19baa8b9560bce05e0559f90086d