Typescript переносит зависимость es6 .js к es5

У меня есть гипотетический файл 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:

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 выводить es5 также на зависимости javascript?

Контекст, если вы заботитесь:

Я сделал ужасную ошибку, используя react-create-app-typescript а также react-scripts-ts как образец для моего приложения React. Встроенный стек веб-пакетов очень уверен в том, откуда должен исходить код, и что скомпилированный источник должен быть es5. Упакованный минификатор / ускоритель потерпит крах, если попытается минимизировать какие- либо артефакты es6. Я знаю, что могу бежать npm run-script eject и изменить различные скрипты конфигурации, но я пытаюсь избежать этого беспорядка. Мне бы очень хотелось, чтобы исходный код компилировался в es6, а не связывался с их стеком веб-пакетов.

3 ответа

Решение

К сожалению, нет способа конвертировать зависимости из ES6 в ES5. Этот вариант в tsconfig.json влияет только на то, как передается код TypeScript. Что вы должны сделать, это использовать версию ES5 вашего helper-from-node-modules, Например, Angular распространяется с несколькими пакетами, для ES5 (umd), ES5, ES6 ... Затем в package.json из библиотеки есть опции, чтобы сообщить упаковщику (обычно веб-пакет), какую версию использовать, в зависимости от целевого использования для TypeScript.

Если используемая вами библиотека не поддерживает это, единственный вариант, который у вас есть, это перенести его на ES5 самостоятельно, возможно, с помощью babel, или использовать альтернативу. Однако странно, что библиотека распространяется только как ES6.

Единственное, что мне приходит в голову, это подключиться к процессу компиляции и преобразовать ваши зависимости до того, как они будут обработаны 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)
            ]
          })
        }
      }
    ]
  }
};

Наткнулся на этот вопрос, потому что мне нужно было импортировать некоторые файлы как в Next.js, так и в мой CLI. (Общий исходный файл в двух разных сборках.) Next.js имеет определенную автоматическую конфигурацию, поэтому я пытался поддерживать все, что он поддерживает, поэтому у меня было не так много ситуаций, когда Next.js работал, а мой CLI терпел неудачу.

Таким образом, приведенное ниже решение является частью Babel. (Я объединил с https://github.com/vercel/next.js/tree/canary/examples/custom-server-typescript для части tsconfig.)

Решение для переноса импорта ES6 в ES5: (вне nextjs)

из https://www.dotnetcurry.com/javascript/1293/transpile-es6-modules-es5-using-babel

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

Создавать :

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

добавить в свой скрипт сборки (т.е. у вас, вероятно, уже есть package.json scriptза npm run buildработать)

для работы JSX (если у вас есть .tsxфайлы или синтаксис JSX в .jsфайлы)

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

И в .babelrc

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

для Next.js _app пришлось добавить https://github.com/uiwjs/babel-plugin-transform-remove-imports , чтобы удалить импорт CSS

Другие вопросы по тегам