了解 Rails 与 webpacker 和在 JS 上的发生率

Understanding Rails with webpacker and incidence on JS

来自正在迁移的遗留应用程序的 rails 6 个应用程序调用:

<%= javascript_pack_tag 'zxing.js' %>
<script type="text/javascript">
  window.addEventListener('load', function () {
    let selectedDeviceId;
    const codeReader = new ZXing.BrowserMultiFormatReader()
    console.log('ZXing code reader initialized')
    codeReader.listVideoInputDevices()
      .then((videoInputDevices) => {
        const sourceSelect = document.getElementById('sourceSelect')
        selectedDeviceId = videoInputDevices[0].deviceId
        if (videoInputDevices.length >= 1) {
          videoInputDevices.forEach((element) => {
            const sourceOption = document.createElement('option')
            sourceOption.text = element.label
            sourceOption.value = element.deviceId
            sourceSelect.appendChild(sourceOption)
          })

          sourceSelect.onchange = () => {
            selectedDeviceId = sourceSelect.value;
          };

          const sourceSelectPanel = document.getElementById('sourceSelectPanel')
          sourceSelectPanel.style.display = 'block'
        }

        document.getElementById('startButton').addEventListener('click', () => {
          codeReader.decodeFromVideoDevice(selectedDeviceId, 'video', (result, err) => {
            if (result) {
              console.log(result)
              document.getElementById('result').textContent = result.text
let formData = new FormData();
let CodeParams = {
code_data: result.text,
shopkeeper_id:  <%= current_user.id %>
};
formData.append("code_json_data", JSON.stringify(CodeParams));
$.ajax({
url: "new_moviment",
type: "post",
data: formData,
   processData: false,
  contentType: false,
 });
            }
            if (err && !(err instanceof ZXing.NotFoundException)) {
              console.error(err)
              document.getElementById('result').textContent = err
            }
          })
          console.log(`Started continous decode from camera with id ${selectedDeviceId}`)
        })

        document.getElementById('resetButton').addEventListener('click', () => {
          codeReader.reset()
          document.getElementById('result').textContent = '';
          console.log('Reset.')
        })

      })
      .catch((err) => {
        console.error(err)
      })
  })

正在加载 javascript,但页面的脚本不是 Uncaught ReferenceError: ZXing is not defined

ZXing documentation 确实根据 Use on browser with ES6 modulesAMDUMDCommonJS.[=32= 提供不同的代码库]

我的印象是,随着迁移到 webpacker,Rails 是在 ES6 下进行预处理。但这种印象被基于浏览器的代码和基于模块的代码这一事实所混淆。

应该如何编辑这个脚本(对于 JS-knotheads 来说,有没有在线工具可以识别和更改 ES6 的语法?)

更新

经过yarn add @zxing/librarypacks/application.js编辑为

require("@zxing/library")
import("../src/qr_scan")

src/qr_scan.js现在如下:

import { BrowserMultiFormatReader, NotFoundException } from '@zxing/library';

window.addEventListener('load', function () {
  let selectedDeviceId;
  const codeReader = new BrowserMultiFormatReader() // note the updated module reference
    console.log('ZXing code reader initialized')
    codeReader.listVideoInputDevices()
      .then((videoInputDevices) => {
        const sourceSelect = document.getElementById('sourceSelect')
        selectedDeviceId = videoInputDevices[0].deviceId
        if (videoInputDevices.length >= 1) {
          videoInputDevices.forEach((element) => {
            const sourceOption = document.createElement('option')
            sourceOption.text = element.label
            sourceOption.value = element.deviceId
            sourceSelect.appendChild(sourceOption)
          })

          sourceSelect.onchange = () => {
            selectedDeviceId = sourceSelect.value;
          };

          const sourceSelectPanel = document.getElementById('sourceSelectPanel')
          sourceSelectPanel.style.display = 'block'
        }

        document.getElementById('startButton').addEventListener('click', () => {
          codeReader.decodeFromVideoDevice(selectedDeviceId, 'video', (result, err) => {
            if (result) {
              console.log(result)
              document.getElementById('result').textContent = result.text

              let formData = new FormData();
              let CodeParams = {
              code_data: result.text
              };
              formData.append("code_json_data", JSON.stringify(CodeParams));
              $.ajax({
              url: 'new_user',
              type: "post",
              data: formData,
                 processData: false,
                contentType: false,
               });
            }
           if (err && !(err instanceof ZXing.NotFoundException)) {
              console.error(err)
              document.getElementById('result').textContent = err
            }
          })
          console.log(`Started continous decode from camera with id ${selectedDeviceId}`)
        })

        document.getElementById('resetButton').addEventListener('click', () => {
          codeReader.reset()
          document.getElementById('result').textContent = '';
          console.log('Reset.')
        })

      })
      .catch((err) => {
        console.error(err)
      })
  })

并且视图页面没有更多 javascript 引用。然而,加载页面会导致控制台出现以下错误:

Uncaught TypeError: _zxing_library__WEBPACK_IMPORTED_MODULE_0__.BrowserMultiFormatReader is not a constructor

指向 codeReader 行。该页面已通过 webpacker 尝试编译进行处理。

尽管 js/zxing-3544fb3b633f87715d29.js 528 KiB zxing [emitted] [immutable] zxing 已成功构建 ([./app/javascript/packs/zxing.js] 524 KiB {zxing} [built]),但两个导入函数均失败:

ERROR in ./app/javascript/src/qr_scan.js 4:23-47
"export 'BrowserMultiFormatReader' was not found in '@zxing/library'
 @ ./app/javascript/packs/application.js

ERROR in ./app/javascript/src/qr_scan.js 47:36-53
"export 'NotFoundException' was not found in '@zxing/library'
 @ ./app/javascript/packs/application.js

在 zxing 编译文件中搜索这些字符串仅显示两个实例:

e.BrowserMultiFormatReader = s;
e.NotFoundException = l["default"]; 

自然导致控制台错误:

window.addEventListener('load', function () {
  var selectedDeviceId;
  var codeReader = new _zxing_library__WEBPACK_IMPORTED_MODULE_0__["BrowserMultiFormatReader"](); // note the updated module reference

当恢复到 library's documentation 引用的命令时,Webpacker 最终编译

const codeReader = new BrowserQRCodeReader() // note the updated module reference
//  const codeReader = new BrowserMultiFormatReader() // note the updated module reference

但是现在,出现控制台错误:

Uncaught ReferenceError: BrowserQRCodeReader is not defined

指向var codeReader = new BrowserQRCodeReader();

JavaScript webpack 中的模块不会导出到全局范围,即,当将 Webpacker 与 Rails 一起使用时,您不能从 [=15] 中引用类似 ZXing 的内容=] 默认情况下在 ERB 模板中标记。

相反,您可以将所有 JavaScript 移动到 app/javascript 目录并更新您的 ZXing(和其他库)引用以使用模块导入。

Rails 会将“packs”文件夹中的所有内容视为一个单独的包。从指向您的源代码的应用程序包开始:

app/
  javascript/
    packs/
      application.js
    src/
      my_barcode.js
// app/javascript/packs/application.js

import '../src/my_barcode'
// app/javascript/src/my_barcode.js

// Based off the module imports described in the ZXing README
import { BrowserMultiFormatReader, NotFoundException } from '@zxing/library/esm';

window.addEventListener('load', function () {
  let selectedDeviceId;
  const codeReader = new BrowserMultiFormatReader() // note the updated module reference
  // and so on ...

并且在您的应用程序布局中:

<%= javascript_pack_tag 'application' %>