javascript - Rails,webpacker : where/when to use the import statement in classes, 以及在 pack/application.js 中要求的目的是什么?

标签 javascript es6-modules webpacker ruby-on-rails-6

我正在将旧应用程序升级到 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"在每个引用它的 JS 文件上?在我的示例中,我想使用 Datepicker在多个地方上课。我问的原因是因为我有10+这样的课,10+有点烦import我想在其中使用的每个 JS 文件顶部的语句。有些类我总是想访问。我玩过 webpacker ProvidePlugin 功能,但它提示 Datepicker不是构造函数,所以我可能遗漏了一些东西,但我没有足够的知识知道什么。

  • 应用程序/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
        }
      }
    }
    
    

    应用程序/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 .在这种情况下,您只需要在自定义日期选择器模块中进行此导入。您可以删除 require("pikaday")从您的 application.js 包文件中。

    这样做的原因是 Webpack 会将您的 application.js 包作为依赖关系图的入口点;从那里开始,它将递归遍历每个必需/导入的模块,查找这些模块的依赖关系,依此类推,直到所有声明的模块都包含在包中。由于您已声明 import 'custom/datepicker'在 application.js 包中,自定义日期选择器导入 pikaday ,它将作为依赖项包含在包中。
  • 您的定制Datepicker被编译为 ES 模块(更确切地说,Webpack 的 ES 模块实现),因为您使用的是 ES 模块语法 export default ... .这对 ProvidePlugin 的工作方式很重要。来自 Webpack 4 documentation of ProvidePlugin :

    For importing the default export of an ES2015 module, you have to specify the default property of module.



    这意味着您为 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

    关于javascript - Rails,webpacker : where/when to use the import statement in classes, 以及在 pack/application.js 中要求的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59364809/

    相关文章:

    javascript - 如何将两个内容 html 的总和转换为 jQuery 脚本

    Javascript 函数没有返回值

    javascript - 如何使用 babel 或 webpack 在 ES6 导入/导出模块中使用 Node.js CommonJS 模块?

    css - React 导入的 css 不可用

    javascript - 将数据从 Rails View 传递到 webpacker 中的 VueJS 组件

    javascript - Rails 下使用 webpacker 进行 Bootstrap-notify 返回 $.notify 不是一个函数

    javascript - 二进制数的 Angular 输入掩码

    javascript - 如何从对象数组中删除项目?

    javascript - 组织 React 组件

    javascript - ES6 模块 - 如果不在 React 组件中则导入的常量未定义