Сравнение двух схем упаковки webpack ts

Webpack

1. Введение

В настоящее время обычно используются две схемы упаковки веб-пакетов:

  1. ts-loader: преобразовать ts в js, а затем использовать babel для преобразования js в более низкую версию js;
  2. @babel/preset-typescript: он напрямую удаляет TypeScript и преобразует его в JS, что увеличивает скорость его компиляции и требует только одного компилятора Babel.

Во-вторых, сравнение программ

Сначала нам нужно установитьwebpack、webpack-cli、typescriptПросто напишите немного ts для тестов упаковки:

// index.ts

class Student {
  name: string
  age: Number
  constructor(name: string, age: Number) {
    this.name = name
    this.age = age
  }

  greet() {
    console.log(`Hello, my name is ${this.name}`)
  }
}

const testPromise = (): Promise<string> => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('1')
    }, 1000)
  })
}

const studentA = new Student('a', 20)
studentA.greet()
testPromise().then(data => {
  console.log('data', data)
})

1. Сравнение методов использования

1) ц-загрузчик:

Установить первымts-loader: npm install ts-loader --save-devНастройте webpack.config.js в проекте:

const path = require('path')

module.exports = {
  mode: 'development',
  entry: './index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js"]
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: 'ts-loader'
      }
    ]
  },
  plugins: []
}

Затем вам нужно установить tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
    "target": "es5",
    "lib": [
      "es5",
      "dom",
      "es2015.promise"
    ]
  }
}

lib также может настраивать другие параметры в соответствии с конкретным кодом и сценариями приложения:

После упаковки вы можете увидеть код упаковки:

Фактический const, стрелочные функции и т. д. были преобразованы в es5, а промисы могут быть несовместимы в браузерах более ранних версий, затем установите babel для преобразования некоторых несовместимых синтаксисов в es5:

npm install core-js
npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill

установить.babelrc;

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3",
        "useBuiltIns": "usage"
      }
    ]
  ]
}

Установите babel-loader для обработки js в webpack.config.js

module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: ['babel-loader', 'ts-loader']
      }
    ]
},

Затем упакуйте его:

Видно, что такие методы, как обещание, были определены, так что это не вызовет проблемы несовместимости с младшими версиями.Конечно, если вы установили Для браузеров старшей версии эта часть кода не будет упакована, потому что браузеры старшей версии уже могут напрямую использовать промисы.

2) @babel/preset-typescript:

В основном то же самое, что и вышеупомянутые плагины bebel.

npm install core-js
npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
npm install --save-dev @babel/preset-typescript

более@babel/preset-typescriptbabel-loader используется непосредственно в webpack.config.js:

const path = require('path')

module.exports = {
  mode: 'development',
  entry: './index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, './dist')
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: ['babel-loader']
      }
    ]
  },
  plugins: []
}

В .babelrc их только больше@babel/preset-typescript

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "corejs": "3",
        "useBuiltIns": "usage"
      }
    ],
    "@babel/preset-typescript"
  ]
}

Выполните упаковку и обнаружите, что bundle.js также упаковывает промисы.
использовать здесь@babel/preset-typescriptКогда я специально удалил tsconfig.js, я обнаружил, что он все еще может быть успешно упакован, ноts-loaderНеобходимо установить tsconfig.js, потому что я только что сделал тест, поэтому я его удалил.В реальном проекте мне все еще нужно установить tsconfig.js.

2. Сравнение времени упаковки

Код ts абсолютно одинаков в обоих сценариях:
ts-loaderВремя упаковки:

около 1000 мс

@babel/preset-typescriptВремя упаковки:

около 500 мс Я чувствую, что улучшение скорости упаковки по-прежнему очевидно, а размер упаковки примерно такой же.

3. Используйте ts для сравнения набора инструментов npm.

Если нам нужно использовать ts для разработки некоторых пакетов npm для инструментов разработки, я действительно рекомендую его.ts-loader:

Давайте сначала создадим два новых проекта, а затем небрежно напишем небольшой тестовый код:

1) ц-загрузчик:

ts-build-loaderдля использованияts-loaderЧтобы разработать пакет npm:

ts-build-loader:  src/index.ts

export function addFn(a: number, b: number): number {
  return a + b
}

В tsconfig.json вам нужно настроить сгенерированный файл объявления проекта:

{
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
    "target": "es5",
    "declaration": true, // 将生成.d.ts文件
    "outDir": "./dist",
    "lib": [
      "es5",
      "dom",
      "es2015.promise"
    ]
  },
  "exclude": [
    "./dist"
  ]
}

В этот момент мы можем выполнитьnpm run buildВзгляните на упакованный код:

js для основного метода проекта и файл объявлений index.d.ts.
Кроме того, если нам нужно использовать файл объявления, который будет запрашиваться при его использовании, вам все равно нужно указать основной файл объявления в package.json:

2) @babel/preset-typescript:

ts-build-babelдля использования@babel/preset-typescriptРазработан пакет npm:

ts-build-babel:  src/index.ts

export function subFn(a: number, b: number): number {
  return a - b
}

воплощать в жизньnpm run build:

даже если яtsconfig.jsonбыл установлен вdeclarationТакже нет файла декларации для проекта.

Наконец-то мы в этих двух проектахpackage.jsonУстановите Main в качестве упакованных JS в:

На данный момент были просто реализованы пакеты npm двух разных схем упаковки.

Создать новый проектtest-ts-npmЧтобы проверить, доступен ли наш инструмент, мы отдельноts-build-loaderа такжеts-build-babelвыполнить вnpm link, затем вtest-ts-npmСвяжите эти два пакета отдельно в:npm link ts-build-loader、 npm link ts-build-babel

Просто установите ts в проект и создайте новыйindex.tsДва класса инструментов, написанные перед файловым тестом:

test-ts-npm:  index.ts

import { addFn } from 'ts-build-loader'
import { subFn } from 'ts-build-babel'

let n = addFn(1, 1)

let m = subFn(1, 1)

console.log(n)
console.log(m)

Первыйtsc index.tsСкомпилируйте ts, затемnode index.jsВыполните скомпилированный js:

Докажите, что оба пакета доступны, и тогда мы сможем выяснить это, сравнив использование самым простым способом.ts-loaderПреимущества разработки пакетов npm очевидны:

  • 1. Не вводите сообщение об ошибке:

когда мы использовалиts-loaderПоскольку файл объявления был сгенерирован при упаковке проекта, такие ошибки, как невозможность найти модуль, здесь сообщаться не будут;

  • 2. Умные подсказки об ошибках: когда мы намеренно пишем неправильный параметр:

Это понятноts-loaderПоскольку в упакованном коде есть файл index.d.ts, при неправильном его использовании vscode выдаст соответствующее сообщение об ошибке. В процессе разработки такой подход явно более разумен.

Наконец, осталось несколько нерешенных вопросов:

    1. @babel/preset-typescriptМожно ли сгенерировать файл объявления проекта, установив;
    1. На самом деле упакованный код хорошо виден: используйтеts-loaderОбъем кода после упаковки будет намного больше, чем@babel/preset-typescriptЗапакованный код пока не нашел разумного объяснения и способа обработки

Я надеюсь, что если кто-то знает, вы можете прокомментировать ниже.Если я найду информацию по актуальному вопросу, я улучшу и дополню ее в кратчайшие сроки.

3. Резюме

Сравните два приведенных выше варианта:

Если проект связан с бизнес-логикой, рассмотрите возможность использования@babel/preset-typescript, конфигурация проще, а скорость упаковки немного выше;ts-loaderВ процессе настройки еще много подводных камней, таких какtsconfig.jsonЛиб не настроен на то, чтобы вызывать ошибку, и при переносе на es5 это фактически решается использованием babel для обработки es6, поэтому используйте его напрямую@babel/preset-typescriptПо ощущениям станет яснее.

Если он используется в качестве инструментария или библиотеки компонентов, связанных с разработкой, рекомендуется использоватьts-loader, Файл объявления проекта может быть автоматически сгенерирован после упаковки, и внедрение в другие проекты будет иметь более удобный опыт разработки.