代码之家  ›  专栏  ›  技术社区  ›  Chris Wilson

在Node模块中,如何将模块分部分导出,以便根据需要分部分导入

  •  1
  • Chris Wilson  · 技术社区  · 4 年前

    这是一个很难向谷歌表达的相当简单的问题:我有一个节点模块,我想分块导出,这样它就可以根据用户想要的数量分块导入,这对文件大小有重大影响。

    我的小模块叫做 Piano-Notes ,它输出一个88长度的简单对象数组,描述钢琴上的每个琴键。

    除此之外,我还下载了 high-quality, public-domain samples from a Steinway ,由爱荷华大学电子音乐工作室提供,每个工作室约10MB .aiff 文件。(这些不包含在仓库中,但可以通过shell脚本下载——请参阅 README 。然后,我执行以下转换(也可以在仓库中作为shell和Node脚本使用):

    • 使用 ffmpeg ,我将每个样本减少到 mp3 500ms、1000ms和2000ms(同时也消除了原件中的小初始静音),这很有用,因为不同的应用需要不同的持续时间。每个音符的样本现在分别为9KB、17KB和33KB。

    • 使用Node,我将样本加载到Buffer中,将其转换为base64,并将其捆绑到 one composite JSON file for each duration 。这些文件为1MB(500ms)、2MB(1000ms)和3.9MB(2000ms)。这消除了用户下载一堆mp3并弄清楚如何让模块定位它们的需要。

    • 这就是我遇到麻烦的地方 :用户应该能够选择她想要的三个样本中的多少个,只导入这些样本,并将它们加载到笔记数组中,这样每个样本都有一个 .play 方法。后一部分在 Notes object's .loadAudio 方法。

    问题是,我的测试都在拉取所有三个样本,生成7MB的文件。我原以为这会奏效(在 ./lib/Audio.js ):

    const AUDIO = {
        500: require("../data/audio/audio_500.json"),
        1000: require("../data/audio/audio_1000.json"),
        2000: require("../data/audio/audio_2000.json")
    }
    
    const Piano_500 = { duration: 500, notes: AUDIO[500] };
    const Piano_1000 = { duration: 1000, notes: AUDIO[1000] };
    const Piano_2000 = { duration: 2000, notes: AUDIO[2000] };
    
    export { Piano_500, Piano_1000, Piano_2000 }
    

    然而,我有 two tests ,其中一个导入所有三个样本,另一个仅导入500ms样本:

    test_all.js

    import { Notes } from '../lib/Notes';
    import { Piano_500, Piano_1000, Piano_2000 } from '../lib/Audio';
    
    /* load samples into a `Notes` instance and export
    export default notes;
    

    test_500ms.js

    import { Notes } from '../lib/Notes';
    import { Piano_500 } from '../lib/Audio';
    
    /* likewise */ 
    export default notes;
    

    这两个测试都会生成一个7MB的文件。理想情况下,第二个大约是1MB,因为它只会加载500ms样本的JSON文件。

    显然,我并不完全理解 imports exports 作品。(我想我不是唯一一个。)我猜这是因为 ./lib/Audio.js 上面的文件需要所有三个, 即使它单独出口 .如何正确编写导出中间件,如 Audio.js 这样一个文件就可以加载模块的所有部分,根据需要进行划分,以及 export 根据需要,这些作品 import ?

    (我持开放态度,认为这是一种处理整个项目的愚蠢方式,MP3应该根据需要加载,但这仍然是我应该理解的!)

    0 回复  |  直到 4 年前
        1
  •  1
  •   jfriend00    4 年前

    在普通node.js中,一个模块一次完全导入,不管导出中有多少个单独的入口点。将其分解以使较小的部分能够独立加载的唯一方法是将其分解为单独的模块,这样API的客户端就可以只加载他们想要加载的模块。

    但是,为了成功地保持较小的模块负载,您必须确保您自己的模块不会各自引入大量其他内容或您自己的大部分其他内容。为了实现客户端可以成功地只加载他们真正想要的东西,并且实现高效和小负载的结果,那么你需要非常仔细的内部模块设计。在这里,代码共享(让许多不同的代码片段共享所有的东西)往往会使实现小的部分加载变得非常复杂,因为API的消费者很容易只加载一个模块,但如果它在内部工作,它最终会拉入你在内部共享的许多其他模块。这是可以做到的,但需要非常仔细的设计,以及准确衡量每个客户端导入的加载大小的能力。