将TypeScript转换为ES6的.js依赖项转换为ES5

20

我在项目中有一个假设的Typescript文件(简化的例子)。

Utils.ts

import * as HelperFromNodeModules from 'helper-from-node-modules';

class Utils {
  static foo() {
    return HelperFromNodeModules.parse(...);
  }
}

导入helper-from-node-modules是包含Javascript文件的操作。

helper-from-node-modules.js:

const dep = require('foo');
function parse(...) {
   return bar.map((e) => {...});
}

来自@types/helper-from-node-modules index.d.ts:

Translated:

And from @types/helper-from-node-modules index.d.ts:

export function parse(...);

tsconfig.json 包含以下内容:

{
  ...
  "target": "es5",
  "lib": ["es2015.collection","es6", "dom"],
  "sourceMap": true,
  "allowJs": true,
  ...
}
因为Typescript编译器输出的文件是由我的编译源代码加上所有依赖项组成的一个巨大拼接文件,而helper-from-node-modules一直都是一个.js文件,所以编译器似乎只是将其内容附加到输出文件中。因此,尽管"target": "es5",输出文件仍然包含es6的特性,如const(e) => {...},导致随后期望严格的es5 javascript的事物发生错误。
有没有一种方法告诉Typescript编译器/转换器在javascript依赖项上输出es5呢? 如果您在意上下文: 我犯了一个可怕的错误,使用了react-create-app-typescriptreact-scripts-ts作为我的React应用程序的样板。Webpack堆栈内置的非常固执己见,必须从哪里获取源代码,编译后的源代码必须是es5。如果尝试缩小任何es6特性,压缩器/混淆包将会崩溃。我知道我可以运行npm run-script eject并修改各种配置脚本,但我试图避免这个混乱。我希望能够将源代码编译为es6,而不搞乱他们的webpack堆栈。
3个回答

11

很遗憾,目前无法将ES6的依赖项转换为ES5。在tsconfig.json中的选项只影响TypeScript代码的转译。您应该使用一个ES5版本的helper-from-node-modules。例如,Angular分发了几个包,其中包括ES5(umd),ES5,ES6等。然后,在库的package.json中,有一些选项可以告诉打包器(通常是webpack)要使用哪个版本,具体取决于要用TypeScript进行的目标。

如果您使用的库不支持此选项,则唯一的选择是自己将其转译为ES5,可以使用babel,或者使用替代库。 然而,仅作为ES6分发的库确实有些奇怪。


5

我想到的唯一办法是在编译过程中钩入,并在 TypeScript 处理依赖项之前对其进行转换。这需要使用 TypeScript 转换器。

转换器是一个函数,它将您程序的 AST 作为输入。以下是一个基本示例:

import * as ts from 'typescript';

export default (program: ts.Program) => {
    return (ctx: ts.TransformationContext) => {
        return (sourceFile: ts.SourceFile) => {
            function visitor(node: ts.Node): ts.Node {
                /**
                 * If that's the kind of node you were looking for,
                 * do something with it and return it. Otherwise:
                 */
                return ts.visitEachChild(node, visitor, ctx);
            }

            return ts.visitEachChild(sourceFile, visitor, ctx);
        };
    };
}

如果你正在使用 Webpack,你可以将它插入到你的构建流程中,在你的 Webpack 配置文件中进行配置。

webpack.config.js

const transformer = require('./your-custom-transformer');

module.exports = {
  /* ... */
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader', // (or 'awesome-typescript-loader')
        options: {
          getCustomTransformers: program => ({
            before: [
              transformer(program)
            ]
          })
        }
      }
    ]
  }
};

1
因为我需要将一些文件导入到Next.js和我的CLI中(两个不同的构建中共用一个常见的源文件),所以我遇到了这个问题。Next.js有特定的自动配置,所以我尝试支持它支持的所有东西,这样就不会出现Next.js可以正常工作而我的CLI失败的情况。
下面的解决方案是Babel部分。(我与https://github.com/vercel/next.js/tree/canary/examples/custom-server-typescript结合使用来处理tsconfig部分。)
将ES6导入转译为ES5的解决方案(在Next.js之外):
来源:https://www.dotnetcurry.com/javascript/1293/transpile-es6-modules-es5-using-babel
npm install --save-dev @babel/cli @babel/preset-env

创建.babelrc文件:
{
  presets: ["@babel/preset-env"]
}

将以下内容添加到您的构建脚本中(即您可能已经有了用于运行npm run buildpackage.json script):

为了使JSX工作(如果您在.js文件中有任何.tsx文件或JSX语法)

npm install --save-dev @babel/preset-react

.babelrc文件中
{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}

对于 Next.js,需要添加 https://github.com/uiwjs/babel-plugin-transform-remove-imports 以移除 CSS 导入。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接