4

我们的应用程序建立在 Next 之上,我们目前正在将我们的录音引擎从 Script Processor 迁移到 Audio Worklet API。(当然具有向后兼容性)过渡的一部分也是升级到 Webpack 5。我们同时使用 Web Workers 和 Audio Worklet。在切换到 Webpack 5 之前,它带有对 Workers 的本机支持,(或者看起来如此)我们使用了worker-plugin。它对两者都非常有效,但是随着过渡我们不再依赖它,因为它使用过时的 webpack 的 API,并且 Next 带有自己的捆绑的 Webpack 4 和 5,它们似乎不包含向后兼容性。

现在的挑战是让这些与 Next 捆绑的 Webpack 5 一起工作。第一个问题来自网络工作者的全局范围未定义。这可以通过设置config.output.globalObject来解决"(typeof self !== 'undefined' ? self : this)"。一旦workers正常工作,下一个问题就会出现在尝试捆绑worklet的代码时。目前,Webpack 5 不支持 worklet 导入,但它们公开了解析器配置,可用于告诉 webpack 将其作为工作程序加载,根据这个Github 问题。这将在 Next 中失败,除非您还设置config.output.publicPath = "/_next/";了在通过 加载块时audioContext.audioWorklet.addModule(...),代码会以 . 崩溃Uncaught TypeError: Cannot read property 'webpackChunk_N_E' of undefined。如果我们检查包含捆绑的 worklet 代码的块,我们将看到这个 prop 正在以下列方式使用:

var chunkLoadingGlobal = (typeof self !== 'undefined' ? self : this)["webpackChunk_N_E"] = (typeof self !== 'undefined' ? self : this)["webpackChunk_N_E"] || [];
var parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);
.
.
.
(typeof self !== 'undefined' ? self : this)["webpackHotUpdate_N_E"] = function...

很明显,它AudioWorkletGlobalScope没有selfor this,所以这就是为什么它不太顺利。

所以问题是,如何解决这个问题?Audio Worklets 似乎仍然很少受到 Next 和 Webpack 的关注,尽管它现在在Safari中也是默认可用的。(自 14.5 起)

下面是代表我们当前状态的代码片段。(我们正在使用打字稿)

next.config.js

module.exports = withPlugins([...], {
  future: {webpack5: true},
  webpack: (config, options) => {
    config.output.globalObject = `(typeof self !== 'undefined' ? self : this)`;
    config.output.publicPath = "/_next/";

    config.resolve = {
      ...config.resolve,
      alias: {
        ...config.resolve.alias,
        "audio-worklet": path.resolve(__dirname, "src/util/audio-worklet")
      }
    }

    config.module.parser = {
      ...config.module.parser,
      javascript: {
        worker: ["AudioWorklet from audio-worklet", "..."]
      }
    }

    config.output.chunkFilename = options.isServer
      ? `${options.dev ? "[name].[hash]" : "[name].[chunkhash]"}.js`
      : `static/chunks/${options.dev ? "[name].[hash]" : "[name].[chunkhash]"}.js`;

    return config;
  }
});

src/util/audio-worklet.ts

export const AudioWorklet = (url: URL) => {
  return url as unknown as string;
};

.../audio-context.ts

import { AudioWorklet } from "audio-worklet";

const audioContext = new AudioContext();
audioContext.audioWorklet.addModule(new AudioWorklet(new URL("path/to/processor.worklet.ts", import.meta.url)));

.../audio-worklet-processor.worklet.ts

// import statements for utility code

class Processor extends AudioWorkletProcessor {
  // Your run of the mill processor code
}

registerProcessor("processor", Processor);

资料来源:

更新

经过大量挖掘,似乎这个问题是由 webpack 在块中导入脚本引起的。具体来说,当我们尝试导入任何重要的代码(例如 lodash)或使用 babel 认为需要使用其 shims 的数据结构时,Webpack 会注入installChunk函数 which uses importScripts,这显然不受 AudioWorklets 支持。这也插入了上面导致Uncaught TypeError: Cannot read property 'webpackChunk_N_E' of undefined.

这是一个一对一地复制它的回购:https ://github.com/thecynicalpaul/test-audio-worklet-webpack5 (nmp i,然后npm run dev

4

0 回答 0