基於 TypeScript + Babel + Rollup 搭建 ts 開發環境

前言

本篇文章講述了基於 TypeScript + Babel + Rollup 搭建 ts 開發環境的解決方案,先贅述了此方案的優劣勢,後按步驟具體講解各個插件的配置方式,以幫助你們瞭解 TS 項目的編譯原理。javascript

如下是該文章示例代碼所依賴的基礎環境,若有不符,配置引導可能沒法正常運行。css

TypeScript + Babel 方案的特色

什麼是 Babel-TypeScript

你們也許在 Babel 官網中看到過一個 preset,叫 @babel/preset-typescript,沒錯,Babel 不只能夠編譯 ES6 的語法糖、對瀏覽器兼容性進行 polyfill 之外,還擴展了對 TypeScript 的支持,但它與官方的 TypeScript 有一些差別,比較特殊。vue

下面,由我來給你們一一道來。java

開發體驗特色

使用 TypeScript + Babel 方案搭建的項目有什麼特色?node

  1. 開發編譯過程,babel 會直接去除 typescript 類型標記,輸出編譯結果git

    1. 速度很快,但沒有類型檢查
  2. 經過 eslint 作語法檢查和類型檢查github

    1. 而且檢查時機是在 commit 時(由 husky 添加的鉤子)
    2. 固然,vscode 對 typescript 的類型檢查也有必定程度的支持
  3. 爲了下降語法檢查帶來的麻煩,經過配置 prettier 來格式化代碼typescript

    1. 保存文件時(須要配置編輯器)觸發 prettier
    2. 執行 git commit 時(由 husky 實現)觸發 prettier

Babel 編譯的劣勢

萬事開頭難,先說說 Babel 編譯的劣勢npm

  1. Babel 編譯 TypeScript 不會作類型檢查,全部的類型聲明都會被 Babel 拋棄掉
  2. 不支持編譯部分語法,好比:import xx = ‘xx’、namespace(可有可無,這些語法都已棄用了)

Typescript 編譯器徹底沒有上述的問題,那爲何還要畫蛇添足使用 Babel 編譯 Typescript 呢?json

Babel 編譯的優點

先苦後甜,再來講說 Babel 的優點

  1. 靈活性 - Babel 支持根據瀏覽器兼容性要求按需編譯,這個 TypeScript 是不支持的,且官方也聲明過不在考慮範圍內
  2. Polyfill - Babel 支持根據瀏覽器兼容性要求按需添加 Polyfill
  3. Plugins/Presets - Babel 支持超級多的 Plugins,並且經過預設 Presets 能夠免去複雜的 Plugins 配置,這點 TypeScript 也不能知足

好,贅述完了,咱們來看一下實戰演練,動手作個 demo。

懶人請執行如下命令,後面的就不用動手了(先查看上面的基礎環境要求,以確保你的環境能夠正常運行如下命令)

git clone https://github.com/lianer/test-babel-typescript.git

建立一個空的 demo 項目

在命令行直接執行這些命令,先搭一個基礎的倉庫腳手架

mkdir test
cd test

npm init

mkdir src
cd src

# 下面多行內容一整段複製執行
cat <<EOF > index.ts
const sum = function (a: number, b: number): number {
  return a + b;
};
console.log(sum(1, 2));
EOF

目錄結構以下

| src
  | index.ts
| package.json

配置 typescript

配置核心要求的 typescript,雖然僅僅會在 lint 的時候用到它

一、安裝 typescript 依賴
yarn add -D typescript
二、添加 tsconfig 配置文件

由於是 demo 項目,沒有太多要求,所以這裏保持默認的配置就足夠了

./node_modules/.bin/tsc --init

配置 rollup、babel 套件

支持對 ts 文件的編譯,產出 js 文件

相關資料

配置引導

一、安裝相關依賴
# 安裝 rollup 套件
yarn add -D rollup rollup-plugin-babel@latest @rollup/plugin-node-resolve

# 安裝 babel 套件
yarn add -D @babel/core @babel/preset-env @babel/preset-typescript
二、添加 .babelrc 配置文件
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript"
  ]
}
三、添加 rollup.config.js 配置文件
const path = require('path');
const babel = require('rollup-plugin-babel');
const nodeResolve = require('@rollup/plugin-node-resolve');
const pkg = require('./package.json');

const extensions = ['.js', '.ts'];

const resolve = function(...args) {
  return path.resolve(__dirname, ...args);
};

module.exports = {
  input: resolve('./src/index.ts'),
  output: {
    file: resolve('./', pkg.main), // 爲了項目的統一性,這裏讀取 package.json 中的配置項
    format: 'esm',
  },
  plugins: [
    nodeResolve({
      extensions,
      modulesOnly: true,
    }),
    babel({
      exclude: 'node_modules/**',
      extensions,
    }),
  ],
};
四、配置 npm scripts

若是先前項目裏尚未 package.json 文件,能夠先經過 npm init 命令初始化一個

"scripts": {
  "build": "rollup -c"
},
五、在 rollup.config.js 中,用到了 package.json - main 配置項,所以別忘了修改一下 package.json
"main": "lib/index.js"
五、測試一下
npm run build

打包成功,輸出結果

> test-typescript-babel@1.0.0 build /dev/test
/dev/test/src/index.ts → lib/index.js...
> rollup -c
created lib/index.js in 460ms

目錄結構

| lib
  | index.js
| src
  | index.ts
| .babelrc
| package.json
| rollup.config.js
| tsconfig.json
| yarn.lock

編譯出的 lib/index.js 文件內容

var sum = function sum(a, b) {
  return a + b;
};

console.log(sum(1, 2));

認真的同窗可能注意到了,Babel 僅僅只是把 TypeScript 類型移除了而已。

注:若是你再這一步報錯了,提示 The "path" argument must be of type string. Received type undefined,則檢查 package.json - main 配置是否有誤

配置 eslint、prettier

支持代碼的類型校驗、語法校驗,以及代碼格式化

相關資料

配置引導

一、安裝依賴
# 安裝 eslint 套件
yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

# 安裝 prettier
yarn add -D prettier

# 安裝 husky、lint-staged 套件
yanr add -D husky lint-staged
二、添加配置文件 .eslintrc.js

.eslintrc.js 文件描述 eslint 語法檢查和 ts 類型檢查的規則

const path = require('path');
module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'plugin:@typescript-eslint/recommended' // Uses the recommended rules from the @typescript-eslint/eslint-plugin
  ],
  parserOptions: {
    project: path.resolve(__dirname, './tsconfig.json'),
    tsconfigRootDir: __dirname,
    ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features
    sourceType: 'module', // Allows for the use of imports
  },
  rules: {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
  }
};
三、添加配置文件 .prettierrc

.prettierrc 文件描述代碼格式化的規則

{
  "semi":  true,
  "trailingComma":  "all",
  "singleQuote":  true,
  "printWidth":  120,
  "tabWidth":  2
}
四、修改 package.json,配置 husky 和 lint-staged

一個很是龐大的項目,eslint 完整檢查可能須要花費幾分鐘的時間。

而 husky + lint-staged 能夠實現只對提交的文件進行檢查,從而提高開發效率。

這樣即便你的項目再大,也僅僅是檢查本次提交的文件,只需幾秒鐘。

"scripts": {
  "lint": "eslint 'src/**/*.{js,ts}'"
},
"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*./src/**/*.{js,ts,json,css,less,md}": [
    "prettier --write",
    "yarn lint"
  ]
}

上述配置能夠實如今執行 git commit 時調用 prettier 格式化代碼,並使用 eslint 作類型和語法的檢查。

五、若是想要保存文件時自動格式化代碼,則須要安裝 vscode 插件 prettier,並作以下配置
"editor.formatOnSave": false, // 全局默認關閉不作格式化,僅針對 js 和 ts 格式化
"[javascript]": {
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
},
"[typescript]": {
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
},

進一步完善打包機制

進一步完善 rollup 的打包機制,支持多任務打包,打包出不一樣項目所需的資源文件。

引入 rimraf, npm-run-all, rollup-plugin-uglify, lodash.merge

相關資料

  • rimraf - 文件刪除工具,用於每次編譯前清空 lib 目錄
  • npm-run-all - npm 命令並行執行工具
  • rollup-plugin-uglify - uglify js 壓縮工具(rollup 版)
  • lodash.merge - 配置合併工具

配置引導

一、 安裝依賴
yarn add -D rimraf npm-run-all rollup-plugin-uglify lodash.merge
二、修改 rollup.config.js
const path = require('path');
const babel = require('rollup-plugin-babel');
const nodeResolve = require('@rollup/plugin-node-resolve');
const uglify = require('rollup-plugin-uglify').uglify;
const merge = require('lodash.merge');
const pkg = require('./package.json');

const extensions = ['.js', '.ts'];

const resolve = function(...args) {
  return path.resolve(__dirname, ...args);
};

// 打包任務的個性化配置
const jobs = {
  esm: {
    output: {
      format: 'esm',
      file: resolve(pkg.module),
    },
  },
  umd: {
    output: {
      format: 'umd',
      file: resolve(pkg.main),
      name: 'rem',
    },
  },
  min: {
    output: {
      format: 'umd',
      file: resolve(pkg.main.replace(/(.\w+)$/, '.min$1')),
      name: 'rem',
    },
    plugins: [uglify()],
  },
};

// 從環境變量獲取打包特徵
const mergeConfig = jobs[process.env.FORMAT || 'esm'];

module.exports = merge(
  {
    input: resolve('./src/index.ts'),
    output: {},
    plugins: [
      nodeResolve({
        extensions,
        modulesOnly: true,
      }),
      babel({
        exclude: 'node_modules/**',
        extensions,
      }),
    ],
  },
  mergeConfig,
);
三、修改 package.json - scripts
"main": "lib/index.umd.js",
"module": "lib/index.esm.js",
"scripts": {
  "lint": "eslint 'src/**/*.{js,ts}'",
  "dev": "rollup -w -c --environment FORMAT:esm",
  "build:esm": "rollup -c --environment FORMAT:esm",
  "build:umd": "rollup -c --environment FORMAT:umd",
  "build:min": "rollup -c --environment FORMAT:min",
  "build": "rimraf lib/* && run-p build:esm build:umd build:min"
},

在這裏,咱們先經過 rimraf 工具清空 lib 目錄,而後再經過 npm-run-all 工具並行 3 個子編譯任務

這裏的 3 個子編譯任務,分別是:

  • build:esm - 編譯出符合 esm 規範的可執行文件,供 Vue、React 等採用 esmodule 規範進行模塊化打包的項目使用
  • build:umd - 編譯出符合 umd 規範的可執行文件,供 jQuery、Vue、NodeJS 等項目使用
  • build:min - 編譯出符合 umd 規範的壓縮的可執行文件
四、測試執行打包命令
npm run build

輸出結果文件

| lib
  | rem.esm.js
  | rem.umd.js
  | rem.umd.min.js

進一步完善工程

統一編輯器的行爲,好比空格、縮進等,並添加 git 忽略列表

一、添加 .editorconfig 配置文件,編輯器安裝相應的 editorconfig 插件,使該項目統一應用相同的空格、縮進等編碼風格
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
二、添加 .gitignore 配置文件,這裏推薦一個 .gitignore 的生成工具 - gitignore.io
# Created by https://www.gitignore.io/api/vuejs,visualstudiocode
# Edit at https://www.gitignore.io/?templates=vuejs,visualstudiocode

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

### VisualStudioCode Patch ###
# Ignore all local history of files
.history

### Vuejs ###
# Recommended template: Node.gitignore

node_modules/
dist/
npm-debug.log
yarn-error.log

# End of https://www.gitignore.io/api/vuejs,visualstudiocode

Result

至此,基於 Rollup + Babel + TypeScript + ESLint 的整套套件的搭建就完成了。

若是有不夠完善的地方,歡迎在文末進行點評[點贊]。

相關文章
相關標籤/搜索