【问题标题】:getting rails webpacker to apply javascripts (both yarn-managed and not) only in specific views让 rails webpacker 仅在特定视图中应用 javascripts(包括纱线管理的和非纱线管理的)
【发布时间】:2021-01-15 11:59:22
【问题描述】:

将旧版 Rails 应用程序迁移到 Rails 6

3 个 javascript 库仅在两个页面上使用,并且给定一个大小,目标是仅在这些页面上调用它们。

yarn add grapheme-splitter

运行正常,但是其他两个库没有通过yarn列出。因此application.js 包含:

require("grapheme-splitter")
import("../src/segments_calculator")
import("../src/segments_viewer")

但是在调用这些脚本时

<%= javascript_pack_tag 'grapheme_splitter' %>
[...]
<%= javascript_pack_tag 'segments_calculator' %>

Webpacker can't find grapheme_splitter in /Volumes/sjt/r/fidel/public/packs/manifest.json. Possible causes: [...]
Webpacker can't find segments_calculator in /Volumes/sjt/r/fidel/public/packs/manifest.json. Possible causes: [...]

在所有最初的原因中,webpacker 被配置为编译(我已经看到它这样做了)并且没有迹象表明这个文件曾经被修改过(相同的创建和修改日期)

development:
  <<: *default
  compile: true

为什么第四个解释是有效的your webpack configuration is not creating a manifest.?我确实看到清单中缺少它,但其他仅在特定页面上使用(并正在运行)的库也是如此。

如何才能让页面运行在只加载特定 javascripts 的情况下,无论是纱线管理的还是非纱线管理的)?

更新

{
  "application.js": "/packs/js/application-3eebddca0d1bd59ab625.js",
  "application.js.map": "/packs/js/application-3eebddca0d1bd59ab625.js.map",
  "entrypoints": {
    "application": {
      "js": [
        "/packs/js/application-3eebddca0d1bd59ab625.js"
      ],
      "js.map": [
        "/packs/js/application-3eebddca0d1bd59ab625.js.map"
      ]
    },
    "foundation-datepicker": {
      "js": [
        "/packs/js/foundation-datepicker-a70417b8f24614757c48.js"
      ],
      "js.map": [
        "/packs/js/foundation-datepicker-a70417b8f24614757c48.js.map"
      ]
    },
    "municipals": {
      "js": [
        "/packs/js/municipals-ba2af3f728fdf4b1104e.js"
      ],
      "js.map": [
        "/packs/js/municipals-ba2af3f728fdf4b1104e.js.map"
      ]
    },
    "what-input": {
      "js": [
        "/packs/js/what-input-f10be0b1923799dfc64d.js"
      ],
      "js.map": [
        "/packs/js/what-input-f10be0b1923799dfc64d.js.map"
      ]
    }
  },
  "foundation-datepicker.js": "/packs/js/foundation-datepicker-a70417b8f24614757c48.js",
  "foundation-datepicker.js.map": "/packs/js/foundation-datepicker-a70417b8f24614757c48.js.map",
  "municipals.js": "/packs/js/municipals-ba2af3f728fdf4b1104e.js",
  "municipals.js.map": "/packs/js/municipals-ba2af3f728fdf4b1104e.js.map",
  "what-input.js": "/packs/js/what-input-f10be0b1923799dfc64d.js",
  "what-input.js.map": "/packs/js/what-input-f10be0b1923799dfc64d.js.map"
}

【问题讨论】:

    标签: javascript ruby-on-rails webpack


    【解决方案1】:

    背景

    “grapheme-splitter”和“segments_calculator”模块的内容包含在“application.js”捆绑文件中。

    当 webpack 编译时,它会创建一个或多个依赖图。按照 Webpack-er 的约定,依赖关系图的“入口点”是 app/javascript/packs/ 目录中包含的文件。这些“包”文件中的每一个都被编译到 public/packs/ 目录中作为输出(假设你没有配置 webpack 来跨包共享模块)。

    快速修复

    因此,将这些行放入您的“application.js”包文件中:

    require("grapheme-splitter")
    import("../src/segments_calculator")
    import("../src/segments_viewer")
    

    您的意思是:将这些模块包含在“application.js”文件中,该文件将输出到 public/packs/ 目录。要在给定页面上呈现这些模块,您需要使用&lt;%= javascript_pack_tag 'application' %&gt;。否则,您可以将这些模块放在不同的包文件中并进行渲染。这应该足以让您入门。

    更好的修复

    但是,您在特定视图中询问了 JavaScript。对于带有现代 JavaScript 打包器(如 webpack)的“页面特定”JavaScript 的推荐方法是使用 dynamic imports 和单个(或很少)包文件。目前,看起来你已经有四个包——“application”、“foundation-datepicker”、“municipals”、“what-input”——对于一个小型应用程序来说(在我看来,一般来说)太多了。您正在冒着重复模块和造成性能瓶颈的风险,as described in this post

    通过动态导入,您可以延迟渲染依赖关系图的部分,并使用事件侦听器或函数调用一次下载和执行小块。一个示例可能如下所示:

    window.addEventListener('DOMContentLoaded', () => {
      if (document.getElementById("graphene-page")) {
        import('../src/graphene-page') // <-- dynamic import
      }
    });
    

    【讨论】:

    • 可能已经掌握了窍门。基本上,如果有人在布局中调用javascript_pack_tag 'application',那么拥有其他具有依赖关系的包会产生模块重复瓶颈的风险(对我来说非常明显)。通过yield 块调用第二个包会导致这种风险;因此,只有没有依赖关系的包才应该以这种方式调用。对于特定于页面的元素(假设很重),那么动态导入将成为遵循的途径。
    • 是的,听起来你的想法是对的。
    猜你喜欢
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2018-07-12
    • 2016-01-16
    相关资源
    最近更新 更多