【问题标题】:Webpack / Vue.js: generate module code at compile-time using ESM dependenciesWebpack / Vue.js:使用 ESM 依赖项在编译时生成模块代码
【发布时间】:2021-09-20 12:50:26
【问题描述】:

环境: webpack 5.44 + vue.js 3.0 + node 12.21

我试图在编译时生成一个模块,以避免在运行时进行昂贵的计算(以及 10Mb 的依赖项,除非在所述计算期间,否则永远不会使用)。基本上在编译时运行:

import * as BigModule from "big-module";
function extract_info(module) { ... }
export default extract_info(BigModule);

将在运行时导入为:

export default [ /* static info */ ];

我尝试使用 val-loader(最新 4.0),这似乎是专为这个用例设计的。

问题: big-module 是 ESM,但 val-loader 显然只支持 CJS。所以我既不能import(“不能在模块外使用导入语句”错误)也不能require(“意外令牌'导出'”错误)。

有什么方法可以让val-loader 以某种方式加载 ESM 模块吗? 请注意,我并不热衷于使用 val-loader,任何其他实现相同目标的技术同样受欢迎.

【问题讨论】:

    标签: node.js vue.js webpack es6-modules commonjs


    【解决方案1】:

    在了解了这个问题和 node/webpack 内部结构之后,似乎有两种可能的方法可以从 CJS 导入 ESM:

    1. 使用动态import()。但它是异步的,因此不适合这里,因为val-loader 需要同步结果。

    2. 将 ESM 转译成 CJS,这是我采用的方法。

    在我的例子中,完全转译是多余的,重写导入/导出就足够了,所以我使用 ascjs 重写 ESM 文件,并使用 eval 来安全地评估结果字符串。

    总而言之:

    // 需要-esm.js 常量 fs = 要求('fs'); 常量 ascjs = 要求('ascjs'); const _eval = 要求('eval'); 功能要求ESM(文件){ 文件 = 要求解决(文件); 返回 _eval(ascjs(fs.readFileSync(file)), 文件, { 要求: requireESM }, true); } module.exports = 要求ESM; // val-loader-target.js const requireESM = require('./require-esm'); const BigModule = requireESM('big-module'); 功能提取信息(模块){...} module.exports = extract_info(BigModule);

    注意:

    • ascjs 在 CJS 模块上使用是安全的,因为它只重写 ESM 导入/导出。所以 big-module 或其依赖项需要 CJS 文件是可以的。
    • _eval 的第三个参数启用递归重写,否则只翻译顶级文件(传递给 requireESM 的文件)。

    【讨论】:

      猜你喜欢
      • 2019-06-01
      • 2017-06-29
      • 1970-01-01
      • 2019-07-10
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      相关资源
      最近更新 更多