基于 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 的整套套件的搭建就完成了。

若是有不够完善的地方,欢迎在文末进行点评[点赞]。

相关文章
相关标签/搜索