typescript(如下简称ts) 官推是脚手架 create-react-app 的ts版本,可自行查阅。可是我没有用它,缘由有2:javascript
- Webpack 版本是3.x,在组内用过4.x重构脚手架以后以后不想再回头配3.x。
- 做为学习项目以及教程,方便贯穿整个项目构建流程。
接下来将分别从一些用到的tsconfig、webpack配置展开来说解css
ts 做为 js 的方言要编译成 js 须要编译器安装(相关参考5分钟上手TypeScript)html
npm install -g typescript
复制代码
编译代码固然也就是:java
tsc 文件名.ts
复制代码
最终默认会在当前目录下生产一个js文件,就是编译后的代码了。node
既然有默认那就有自定义配置,如何作呢?react
自定义配置有两种方式:webpack
在命令行后加相应配置参数例如你不想将如下代码编译成es5的函数形式(配置参考连接:compiler-options)git
const fuc = ()=>{
console.log(1);
}
fuc();
复制代码
你能够es6
tsc 文件名.ts --target es6
复制代码
若是须要多个配置,继续日后写便可,这里就不详述了。github
第一种方式若是参数多了看上去很难受,这里我推荐第二种方式:在项目跟目录新建tsconfig.json文件,我推荐在方法1文档上找到一个配置参数**--init**初始化tsconfig.json(参考连接:tsconfig.json)。
tsc --init
复制代码
这里我列举几个用到的属性
{
"compilerOptions": {
"target": "es5", // 你最终编译成js模型
"lib":[
"es2017",
"dom"
],// 你使用的一些库,你能够理解成ts的一些polyfill
"module": "ESNext", // 你编译后的代码的模式,amd umd esmodule...等等下面详述
"jsx": "react", // jsx 语法糖用哪一个
"allowJs": true, // 是否容许引入js
"checkJs": true, // 是否检测js文件类型
"paths": {
"@components/*": ["./src/components/*"],
"@utils/*": ["./src/utils/*"],
"@view/*": ["./src/view/*"],
"@styles/*": ["./src/styles/*"],
"@api/*": ["./src/api/*"],
"@store/*": ["./src/store/*"],
"@decorators/*": ["./src/decorators/*"],
"@assets/*": ["./src/assets/*"],
},// 别名
"strict": true, //严格模式
"moduleResolution": "node", // 直接看这个吧https://www.tslang.cn/docs/handbook/module-resolution.html
"baseUrl": ".", // 配合paths,当符合 paths 规则的文件引入,会采用baseUrl+相应数组列表下查找的方式去找相应文件
// "esModuleInterop": true, // 做用是让commonjs/esmodule两种模块模式正常通讯(具体看下一节),做用同下,若是使用了es7相关polyfill不可用会报错(不肯定,我的经验)。
"allowSyntheticDefaultImports": true, // 往下看模块机制
"experimentalDecorators": true, // 使用装饰器
"rootDir": "./src", // 运行tsc命令时去编译哪一个目录下的文件配合webpack能够不设置
"outDir": "./dist" // 一样,其实这个也能够不设置,可是若是不设置你要给js文件写d.ts(后文会讲到)这里会报一个overWrite的错,做为强迫症就设置一下吧。
},
"include": [
"src/**/*"
], // tsc 会编译在->rootDir<-内哪些文件
"exclude": [
"node_modules",
"dist",
"build"
] // tsc 不会编译->rootDir<-内的哪些文件
}
复制代码
Ps:文件新建好了以后若是要编译当前子文件夹,配置是无效的:
tsc ./sub/文件名.ts # 配置无效仍是默认配置
复制代码
经过编译后的几种模块模式来帮助理解module
和esModuleInterop
、allowSyntheticDefaultImports
配置项;
// 原始代码
const fuc = ()=>{
console.log(1);
}
export default fuc();
// commonjs
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fuc = function () {
console.log(1);
};
exports.default = fuc();
// amd
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fuc = function () {
console.log(1);
};
exports.default = fuc();
});
复制代码
原始代码在 commonjs
和 amd
导出的数据格式实际上是这样子的(若是不知道defineProperty
能够查下mdn):
{
__esModule: true,
default:fuc()
}
复制代码
当在某处遇到一行代码引用了
import fuc from '这个地址';
console.log(fuc);
复制代码
当咱们加上esModuleInterop
或allowSyntheticDefaultImports
它会被编译成
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var complie_1 = __importDefault(require("./complie"));
console.log(complie_1.default);
复制代码
require("./complie")
这玩意儿就是上面说的那个对象
而后来分析 __importDefault
,首先会识别__esModule
变量,若是为true
,直接把当前模块做为导出,不然导出一个对象,对象的default是导出的模块。
当咱们不加上面那两个选项的时候编译成
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var complie_1 = require("./complie");
console.log(complie_1.default);
复制代码
小结一下:import variable from 'xx'
variable 会被转成 variable.default;若是配置了esModuleInterop
或allowSyntheticDefaultImports
,若是import
的是esmodule
直接采用当前模块,不然把当前模块放到一个含default
的对象中去,default的值就是当前模块。
OK,接下来咱们来解释这两个属性的意义,引入@types/react/index.d.ts
一段代码(d.ts是啥以后再探讨)
export = React;
export as namespace React;
复制代码
咱们发现没有默认值导出值,可是咱们想import React from 'react'
这种操做就会报错,OK结论就是这两句话,可是过程。。很曲折。
再看下另一种引入和导出方式会如何转换
// module x
export const a = 1;
export const b = 1;
export const c = 1;
export const d = 1;
export default 10;
// module import module x
import * as all from 'x';
console.log(all)
// 转化事后
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.a = 1;
exports.b = 1;
exports.c = 1;
exports.d = 1;
exports.default = 10;
//----------------------------------
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var all = __importStar(require("x"));
console.log(all);
复制代码
一样esModule原样导出,不然取当前对象上的属性导出(剔除原型链上的属性);这里引入的变量不会被处理成all.default
;
我眼中的webpack
他是一个资源整合工具,通过:资源->入口->loader + plugin->output这样一个过程,进行策略整合。本小结不详细讲解配置过程,只是描述下配置思路,具体配置项可点我查看。
首先咱们给本身定一个小目标赚他一个亿,别走错片场了,咱们的项目须要:
autoprefixer
并额外导出,js我想压缩;接下来咱们一个一个实现这些小目标:
具体过程我就不详述了若是你想看demo就点我吧