【问题标题】:Possible to transform a file served by express static? Or stream a require?可以转换由 express static 提供的文件吗?还是流式传输需求?
【发布时间】:2016-12-17 03:19:02
【问题描述】:

在我的通用 JavaScript 应用程序中,我有通过 webpack DLL plugin 提取的 DLL 库,但我必须在默认导出(供浏览器使用)或 commonjs(供 Node 使用)之间进行选择。

在所有数千行供应商代码中,从字面上看,两个导出之间的唯一区别是第一行:

- module.exports =
+ var vendor = 

我的 express 应用程序只允许我使用 require module.exports 变体,因为它需要 commonjs 模块,并且我的浏览器不知道该怎么做,除非它获得 var vendor 变体。

我不希望同一文件有 99.999999...% 的相同副本。

本能地,这感觉很疯狂:我认为这两个环境应该能够使用相同的 DLL 库,因为它们之间的应用程序代码是相同的。

所以我一直在集思广益,并提出了以下可能性:

  • 使用像 RequireJS 这样的客户端 CommonJS 加载器(真的不喜欢这个选项,因为我不得不以加载时间为代价强制在客户端下载)
  • 通过 Express(或 Nginx,如果可能的话)即时转换 DLL 以在客户端请求它们时替换第一行;不确定我使用这种方法会招致什么性能损失。
  • 需要在 Express 应用启动时执行查找/替换的 FileStream 中的 DLL(同样,不知道是否可行,但这感觉是三个选项中侵入性最小的一个)。
  • 接受这样一个事实,即无法避免拥有两个 DLL 副本,并且我添加到我的 DLL 中的每个新依赖项都需要 × 2 磁盘空间等。

我一直未能找到中间两点的实施细节,或寻找替代方法。我正在寻找“只需拥有两份并继续你的生活”之外的答案。如果您知道如何做到中间两点,我很乐意从您那里获得实施细节。如果您有我未在此处列出的想法或方法,我会全力以赴!

【问题讨论】:

    标签: javascript express nginx webpack


    【解决方案1】:

    当然,当我发布我的 SO 问题时,我会在正确的 Google 搜索中找到this solution。一个小时前我从未听说过 vm 模块,但它似乎提供了我正在寻找的东西。

    使用var NAME = 为浏览器构建DLL(这是默认行为)。然后,在服务器上,使用vm.runInNewContext 评估磁盘中的文件并返回新上下文,其中的键与您的DLL 中的var 语句匹配。最后,只需将这些键分配给 global.NAME 并繁荣:服务器理解文件。

    这是我的代码(当前)的样子:

    const vm = require('vm');
    const fs = require('fs');
    
    // from a custom webpack plugin I wrote, where keys are the name of the chunk
    // and the value is a relative filepath to that chunk
    const chunks = require('path/to/my/chunks.json');
    
    if (!chunks.js.serverDLL || !chunks.js.appDLL) {
      throw new Error('Chunks could not be loaded!!');
    }
    
    const dllContext = ((pathMap, context = {}) => {
      Object.keys(pathMap).forEach((key) => {
        vm.runInNewContext(fs.readFileSync(pathMap[key]), context, pathMap[key]);
      });
    
      return context;
    })({ serverDLL: `.${chunks.js.serverDLL}`, appDLL: `.${chunks.js.appDLL}` });
    
    global.serverDLL = dllContext.serverDLL;
    global.appDLL = dllContext.appDLL;
    

    上面还有改进的余地,因为我可能会使用 HOC 函数来迭代我的块输入,而不是硬编码键。另外,我的publicPath 设置为/,但传入我的vm.runInNewContext 的路径需要是相对文件路径。由于我仅在生产环境中执行此操作(而不是开发环境),因此我的构建目录是平面的(无论如何对于这些文件),所以我在前面添加了一个 .,它将客户端 URL 路由转换为适当的相对文件路径。另外,这是我第一次使用vm,所以我相信有人会指出我可以在上面做得更好的方法。 :D

    【讨论】:

      【解决方案2】:

      听起来对文件开头和结尾的更改可能有效:

      // start of file
      try {
        module.exports;
      } catch (err) {
        var module = {};
      }
      var vendor = // ... the duplicated code
      
      // end of file
      module.exports = vendor;
      

      我确信 nodejs 和浏览器通常都可以通过这种方式获取它们的正确值,但我自己并没有将 DLL 库与 webpack 一起使用,所以如果这不适合这种情况,我提前道歉。我想我会把它扔在那里以防万一。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-29
        • 1970-01-01
        • 2017-04-02
        • 2014-08-05
        • 1970-01-01
        • 1970-01-01
        • 2015-05-05
        • 2011-03-11
        相关资源
        最近更新 更多