问题描述
我试图通过 webpack 将下面显示的 emitPrefixes
Typescript 源代码捆绑到一个纯 javascript 文件中,但失败了。
生成的 javascript 代码将在我无法控制的上下文中进行评估,其中已经定义了emit() 函数(在 CouchBase、CouchDB、Cloudant 等基于 JS 的 map reduce 功能中)。结果源必须计算为一个函数。
相同的源代码使用 typescript transpile 成功转换为纯 javascript。但是,我需要 webpack 进行转译,以便将任何导入的模块捆绑到一个 javascript 文件中(转译叶需要完整无缺,但我相信 webpack 可以内联它们)。
但是,即使是这个基本的函数源文件(只导入类型而没有代码),我也无法让 webpack 成功转译。我的怀疑:没有对 emitPrefixes
函数的引用意味着 webpack 正在优化/treeshaking 函数不存在。
有谁知道我需要查看哪些 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 文件中,其中没有任何实际代码。下面的示例显示了编译产生的一些模块元数据。使用 tsconfig.json 中的 "module": "es2015"
甚至缺少此模块元数据,因此 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);
})();
相比之下,打字稿转译程序输出这个,它正确地评估为一个函数,这几乎正是我想要的(除了 __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();
webpack 自动检测的 tsconfig.json 看起来像...
{
"compilerOptions": {
"target": "es5","strict": true,"skipLibCheck": true,"forceConsistentCasingInFileNames": true
}
}
以下参考 typescript transpile 操作成功生成正确的代码,但根据需要保留导入的模块,没有内联它们,这就是为什么我需要让 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);
解决方法
我发现配置对象接受 optimisation configuration。将以下属性添加到传递给 webpack 的配置对象会导致从原始函数可读的源代码使其通过输出
它带有很多 webpack 样板文件,我现在正在研究如何删除,但它就在那里!
optimization: {
minimize: false,usedExports: false,},