前言
最近在搞一个公司用的插件开发环境,环境是以TypeScript+Webpack+ESlint+Sass并支持polyfill为基础进行配置的 但是在配置的过程中TypeScript与其他工具的配合上总会出现一些坑,而这些坑是我翻了很多国外论坛、知乎提问、去github仓库找到两年前的issue才解决的,所以在此记录分享一下,希望可以帮助需要的人躲避这些坑。
TypeScript支持polyfill
起初我在TypeScript文档中找到,配置tsconfig.js,其中 compilerOptions 参数中 lib 这个配置,中文文档中的描述为:
编译过程中需要引入的库文件的列表。
所以我一直认为只要在lib中声明了es2015.promise 它就可以智能的为我引入promise
{
"compilerOptions" :{
"lib":["dom", "scripthost", "es5","es2015.promise"],
...
},
...
}
然而并不会这样,在配置文件中lib的实际作用是声明我们环境中TypeScript文件支持的语法方式。
简单一句话不易理解,我们来测试一下:
如果把lib中的"dom"删掉,那么如果你在写代码的时候使用JS创建了一个Element(dom)元素,在编译的时候是不允许的。
如果你使用了VScode,它会根据你tsconfig.js的配置文件,直接在使用了Element的代码片段告诉你,当前配置是不允许使用Element。
如果我们把lib中的"dom"添加回去,则编辑器就没有错误提示了:
同时,lib这个字段是可选项,我们可以不配置它,它会有默认的配置,根据target的值不同,它的默认值也不同
//target = es5
{
"compilerOptions" :{
"target":"es5"
//"lib":["dom", "scripthost", "es5"]默认值
...
},
...
}
//target = es6
{
"compilerOptions" :{
"target":"es6"
//"lib":["dom", "scripthost", "es6","dom.iterable"]默认值
...
},
...
}
那么 lib 中的配置究竟都做了什么呢?
比如上面我想要让它支持promise,我在lib中就添加了"es2015.promise"的值
打开node_modules找到typescript文件夹,他下面有一堆的lib.xx.xx文件
看看lib.es2015.promise都做了什么, 它只是对promise方法做了类型语法的检测支持
所以问题到这里就迎刃而解了,单独的配置lib属性并不会带来支持polyfill的实际作用
我们需要安装core-js
yarn add core-js --dev
然后在需要使用polyfill的文件中引用它
import * as Promise from 'core-js-pure/features/promise';
由于我不希望我插件中的promise对全局的方法造成污染
所以我调用了core-js-pure中的promise,而不是core-js/features/promise注意两者的区别
另外记得配置下tsconfig.js的module参数为commonjs
{
"compilerOptions" :{
"module":"commonjs",
...
},
...
}
注意这里有坑:
core-js的官方代码中,推荐我们引用方式是
import Promise from 'core-js-pure/features/promise';
而不是
import * as Promise from 'core-js-pure/features/promise';
但它推荐的方式在typescript中编译后会报错,不符合typescript的语法
我在tsconfig.js中的module参数尝试了umd/esnext/es2015都没办法正常打包
但当使用commonjs模式就可以正常使用了,需要注意一下
配置后大功告成,环境已经可以根据需求支持polyfill了 ~
ESLint配合TypeScript使用
现在很多其他文章的配置已经被淘汰了,或者git仓库也不再维护,我也是顺藤摸瓜找到的一份配置方案,其中也有一些坑,在此作记录。
先列出需要安装的扩展:
yarn add eslint eslint-loader @typescript-eslint/parser @typescript-eslint/eslint-plugin --dev
eslint和eslint-loader就不多说了,一个是基础支持库无需配置,一个是webpack检测文件处理的loader
这里主要介绍下后面两个
@typescript-eslint/parser
由于eslint默认是不支持检测typescript的,我们需要安装它的扩展,让它支持typescript的语法,所以它必不可少
@typescript-eslint/eslint-plugin
但当我们有了它的功能后,我们如何设定它的规则?于是官方提供了一套规则的扩展插件,也就是它了
配置ESLint
当我看到官方提供了一套这么友好简单易读的默认配置,我的内心是非常激动的,在解决typescript支持polyfill的问题上我已经心神憔悴了,它的出现就像夏日夜晚里的一阵微风,你以为是凉爽的,结果吹到脸上却热得发烫,让人失望,因为这个配置会报错!
//在根目录创建.eslintrc.js
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/restrict-plus-operands": "error"
//这里就调用了@typescript-eslint/eslint-plugin的rule配置,更多配置可以去github上查文档
}
}
//运行后报错
Parsing error: ImportDeclaration should appear when the mode is ES6 and in the module context
这个ImportDeclaration是什么东西?这个错误该如何解决?我的大脑比较蒙,按照以往的逻辑,国内的搜索引擎直接pass掉,肯定找不到答案,于是我来到了stackoverflow.com企图找到解决方案,结果比较遗憾,只搜到了一条相关的问题,而里面的回答也没有参考性,最终在github的issue看到有很多人也遇到过,但是问题都是一两年前的,解决方案都是让它们升级版本,而我们在当前时间线的版本已经是最新的了!开发人员真是鬼才啊,两年前的bug又复现了呢
翻阅了四五个issue后,在绝望之际找到了解决方案,在parserOptions新增三个参数即可(ecmaVersion、sourceType、ecmaFeatures)
//在根目录创建.eslintrc.js
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,//也就是ES6语法支持的意思
"sourceType": "module",
"ecmaFeatures": {
"modules": true
},
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/restrict-plus-operands": "error"
//这里就调用了@typescript-eslint/eslint-plugin的rule配置,更多配置可以去github上查文档
}
}
如此一来ESLint即可与TypeScript搭配使用了!
结尾
另外我发现webpack在编译typescript后没有办法压缩,需要借助webpack的uglifyjs-webpack-plugin插件来进行压缩, 在配置TS环境有很多坑,而每个人根据 需求遇到的问题可能不同,还需耐心解决!