Попытка объединить typescript в один файл создает загадочный мусор

#typescript #webpack #bundle #tree-shaking #ts-loader

#typescript #webpack #пакет #встряхивание дерева #ts-загрузчик

Вопрос:

Я пытаюсь объединить emitPrefixes исходный текст Typescript, показанный ниже, в один чистый файл javascript через webpack, но потерпел неудачу.

Результирующий код javascript будет оцениваться в контексте, который я не контролирую, в котором функция emit() Уже определена (в рамках карты на основе JS уменьшает функциональность CouchBase, CouchDB, Cloudant и т. Д.). Результирующий источник должен быть преобразован в функцию.

Тот же источник успешно переносится на чистый JavaScript с использованием typescript transpile. Тем не менее, мне нужен webpack для выполнения переноса, чтобы объединить все импортированные модули в один файл javascript (transpile оставляет требования неповрежденными, но я считаю, что webpack может встроить их).

Однако я не могу заставить webpack успешно перенести даже этот исходный файл базовой функции (который импортирует только типы и не содержит кода). Мое подозрение: отсутствие ссылок на emitPrefixes функцию означает, что webpack оптимизирует / отключает функцию от существования.

Кто-нибудь знает, на какие настройки webpack мне нужно обратить внимание, чтобы предотвратить оптимизацию процесса сборки и, следовательно, удаление всего моего кода. Я пробовал много комбинаций без радости.

Вот источник, который я передаю. В этом случае у него нет импортированных значений (только типы, которые удаляются).

 import type { EmitFunction } from "../../../../../lib/mapreduce";
import type { Word } from "../../types";

declare var emit: EmitFunction<string>;

function emitPrefixes(doc: Word) {
  if (doc?.type === "word") {
    emit(doc.id);
  }
}

emitPrefixes;
 

После добавления необходимого правила для использования ts-loader webpack сообщил об успешной компиляции файла prefix.ts. Однако он выводит бессмысленный мусор в prefix.js файл, в котором нет ни одного фактического кода. В приведенном ниже примере показаны некоторые метаданные модуля, выдаваемые компиляцией. "module": "es2015" В tsconfig.json отсутствуют даже метаданные этого модуля, и, следовательно, webpack генерирует пустой файл.

 (() => {
  "use strict";
  var r = { 568: (r, t) => {} },
    t = {};
  !(function e(s) {
    if (t[s]) return t[s].exports;
    var o = (t[s] = { exports: {} });
    return r[s](o, o.exports, e), o.exports;
  })(568);
})();

 

В отличие от этого, процедура typescript transpile выводит это, которое правильно вычисляет функцию, и это в значительной степени именно то, что я хочу (кроме фрагмента __esModule)…

 Object.defineProperty(exports, "__esModule", { value: true });
function emitPrefixes(doc) {
    if ((doc === null || doc === void 0 ? void 0 : doc.type) === "word") {
        emit(doc.id);
    }
}
emitPrefixes;
 

Процедура webpack, которую я использую для компиляции исходного кода, приведена ниже. Кто-нибудь может увидеть, какие параметры конфигурации webpack, возможно, потребуется установить, чтобы остановить его оптимизацию всего моего кода в небытие, потому что на функцию нет ссылок?

 import path from "path";
import webpack from "webpack";

function promiseBundledSource(sourcePath: string): Promise<void> {
  const entry = `./${path.basename(sourcePath)}`; //webpack needs explicit relative path
  const context = path.dirname(sourcePath);
  const config = {
    entry,
    context,
    output: {
      path: context,
      filename: entry.replace(/.ts$/, ".js"),
    },
    module: {
      rules: [
        { test: /.ts$/, use: "ts-loader" },
        {
          test: () => true,
          sideEffects: true,
        },
      ],
    },
  };
  return new Promise((resolve, reject) => {
    webpack(config, (err, stats) => {
      if (err) {
        reject(err);
      } else if (stats?.hasErrors()) {
        reject(stats.compilation.errors);
      }
      resolve();
    });
  });
}

async function run() {
  try {
    await promiseBundledSource(path.resolve(
      "./test/lib/testdomain/index/map/prefix.ts"
    ));
  } catch (error) {
    console.log(error);
  }
}

run();
 

tsconfig.json, который автоматически обнаруживает webpack, выглядит следующим образом…

 {
  "compilerOptions": {
    "target": "es5",
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
 

Следующая ссылочная операция переноса typescript успешно генерирует правильный код, но оставляет импортированные модули по мере необходимости, без их встраивания, поэтому мне нужно, чтобы webpack обрабатывал его вместо этого…

 import fs from "fs";
import {
  transpile,
  ScriptTarget,
  ModuleKind,
  ModuleResolutionKind,
} from "typescript";

const sourcePath = "./test/lib/testdomain/index/map/prefix.ts";

const jsSource = transpile(fs.readFileSync(sourcePath).toString(), {
  target: ScriptTarget.ES5,
  module: ModuleKind.None,
  moduleResolution: ModuleResolutionKind.NodeJs,
  noImplicitUseStrict: true,
  esModuleInterop: false,
  strict: false,
});

console.log(jsSource);

 

Ответ №1:

Я обнаружил, что объект config принимает конфигурацию оптимизации. Добавление следующего свойства к объекту конфигурации, переданному webpack, привело к тому, что исходный код из исходной функции был доступен для чтения

Он прибыл с большим количеством шаблонов webpack, которые я сейчас пытаюсь решить, как удалить, но он есть!

     optimization: {
      minimize: false,
      usedExports: false,
    },
 

Комментарии:

1. Наконец, я использовал накопительный пакет, который работал более или менее мгновенно (с параметром treeshake: false) и не приводил к большому количеству ненужного мусора в модуле webpack IIFE.