简体   繁体   English

Typescript 将 es6.js 依赖转译为 es5

[英]Typescript transpile es6 .js dependency to es5

I have a hypothetical Typescript file in my project (simplified example).我的项目中有一个假设的 Typescript 文件(简化示例)。

Utils.ts :工具.ts

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

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

Importing helper-from-node-modules consists of a Javascript file. helper-from-node-modules包含一个 Javascript 文件。

helper-from-node-modules.js : helper-from-node-modules.js

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

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

export function parse(...);

The tsconfig.json among other things contains the following: tsconfig.json包含以下内容:

{
  ...
  "target": "es5",
  "lib": ["es2015.collection","es6", "dom"],
  "sourceMap": true,
  "allowJs": true,
  ...
}

So my problem is the Typescript compiler's output file is a giant concatenation of my compiled source code plus all of the decencies.所以我的问题是 Typescript 编译器的 output 文件是我编译的源代码加上所有规范的巨大串联。 Since helper-from-node-modules was always a .js file, the compiler seems to just append its contents to the output file.由于helper-from-node-modules始终是一个.js文件,编译器似乎只是 append 其内容到 output 文件。 So, despite "target": "es5" the output file still contains es6 artifacts like const and (e) => {...} , resulting in errors with things later that expect strictly es5 javascript.因此,尽管"target": "es5" output 文件仍然包含es6工件,如const(e) => {...} ,导致以后严格期望es5 javascript 的东西出错。

Is there is a way to tell the Typescript compiler/transpiler to output es5 on the javascript dependencies as well?有没有办法在 javascript 依赖项上也将 Typescript 编译器/转译器告知 output es5

Context if you care:如果您关心上下文:

I made the horrible mistake of using react-create-app-typescript and react-scripts-ts as the boilerplate for my React app.我犯了一个可怕的错误,那就是使用react-create-app-typescriptreact-scripts-ts作为我的 React 应用程序的样板。 The webpack stack built in is very opinionated on where source code should come from and that the compiled source must be es5 .内置的 webpack 堆栈对于源代码应该来自哪里以及编译源必须es5非常固执己见。 The minifier/uglifier packaged will crash if attempting to minify any es6 artifacts.如果尝试缩小任何es6工件,打包的缩小器/丑化器将崩溃。 I know I can run npm run-script eject and modify the various config scripts but I am trying to avoid that mess.我知道我可以运行npm run-script eject并修改各种配置脚本,但我正在努力避免这种混乱。 I would love to just get the source to compile to es6 and not mess with their webpack stack.我很乐意只获取编译为es6的源代码,而不是弄乱他们的 webpack 堆栈。

Unfortunately, there isn't a way to do convert dependencies from ES6 to ES5. 不幸的是,没有办法将依赖关系从ES6转换为ES5。 That option in tsconfig.json only affects how TypeScript code is transpiled. tsconfig.json该选项仅影响如何转换TypeScript代码。 What you should do is use an ES5 version of your helper-from-node-modules . 您应该做的是使用helper-from-node-modules的ES5版本。 For example, Angular is distributed with several packages, for ES5 (umd), ES5, ES6 ... Then, in the package.json of the library there are options to tell the packager (usually webpack) what version to use, depending on the target use for TypeScript. 例如,Angular随ES5(umd),ES5,ES6一起分发了多个软件包。然后,在库的package.json中,有一些选项可以告诉打包程序(通常是webpack)使用哪个版本,具体取决于TypeScript的目标用途。

If the library you're using does not support that, the only option you have is to transpile it to ES5 yourself, maybe using babel, or use an alternative. 如果您使用的库不支持该库,那么您唯一的选择是自己将其转换为ES5,或者使用babel或使用其他方法。 Is is strange, however, for a library to be only distributed as ES6. 但是,对于一个仅作为ES6分发的库来说,这是很奇怪的。

The only thing that comes to my mind is hooking into the compilation process and transforming your dependencies before they get processed by TypeScript. 我唯一想到的是, TypeScript处理依赖之前,请先进入编译过程并对其进行转换。 This requires TypeScript transformers . 这需要TypeScript转换器

A transformer is a function to which the AST of your program is exposed. 转换器是程序的AST所暴露的功能。 A basic example: 一个基本的例子:

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);
        };
    };
}

If you are using Webpack, you could plug it into your build pipeline in your Webpack configuration file. 如果您使用的是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)
            ]
          })
        }
      }
    ]
  }
};

Came across this question because I needed to import some files into both Next.js and my CLI.遇到这个问题是因为我需要将一些文件导入到 Next.js 和我的 CLI 中。 (A common source file in two different builds.) Next.js has certain automated configuration, so I was trying to support all the things it supports so I didn't have many situations where Next.js worked and my CLI failed. (两个不同版本中的公共源文件。)Next.js 具有某些自动配置,因此我试图支持它支持的所有内容,因此我没有遇到 Next.js 工作并且我的 CLI 失败的情况。

So the below solution is the Babel part.所以下面的解决方案是 Babel 部分。 (I combined with https://github.com/vercel/next.js/tree/canary/examples/custom-server-typescript for the tsconfig part.) (我结合https://github.com/vercel/next.js/tree/canary/examples/custom-server-typescript的 tsconfig 部分。)

Solution to transpile ES6 imports to ES5: (outside of nextjs)将 ES6 导入转换为 ES5 的解决方案:(在 nextjs 之外)

from https://www.do.netcurry.com/javascript/1293/transpile-es6-modules-es5-using-babel来自https://www.do.netcurry.com/javascript/1293/transpile-es6-modules-es5-using-babel

npm install --save-dev @babel/cli @babel/preset-env

Create .babelrc :创建.babelrc

{
  presets: ["@babel/preset-env"]
}

add to your build script (ie you probably already have package.json script for npm run build to work)添加到你的构建脚本(即你可能已经有package.json script npm run build工作)

for JSX to work (if you have any .tsx files or JSX syntax in .js files)让 JSX 工作(如果你有任何.tsx文件或.js文件中的 JSX 语法)

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

and in .babelrc.babelrc

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}

for Next.js _app had to add https://github.com/uiwjs/babel-plugin-transform-remove-imports to remove CSS imports对于 Next.js _app 必须添加https://github.com/uiwjs/babel-plugin-transform-remove-imports以删除 CSS 导入

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM