Typescript+React模板搭建(三)
整理于网络
# 一、项目初始化
# 1.1 创建项目
确保安装了
npm install -g typescript
# -S 是--save简写
# -D 是--save-dev简写
# 创建目录
mkdir ts-react && cd ts-react
# 生成package.json、tsconfig.json
npm init -y && tsc --init
# 安装开发工具
npm install-D webpack webpack-cli webpack-dev-server
# 安装react相关
npm install -S react react-dom
# 安装react相关的ts验证包
npm install -D @types/react @types/react-dom
# 安装ts-loader(或者awesome-typescript-loader) 这两款loader用于将ts代码编译成js代码
npm install -D babel-loader
# 1.2 webpack配置
- 在项目根目录新建一个
build文件夹
mkdir build && cd build && touch webpack.config.js
- 根目录下新建src文件夹,然后在src里新建index.tsx文件作为项目入口
mkdir src && cd src && touch index.tsx
- 编写简单的
webpack配置,只包含entry和output
const path = require('path')
module.export = {
entry: {
app: path.join(__dirname, '../', 'src/index.tsx)
},
output: {
path.join(__dirname, '../', 'dist),
filename: '[name].js
}
}
- 编写
awesome-typescript-loader配置项: 在webpack中的module是专门用来决定如何处理各种模块的配置项,例如本例中的typescript,这里主要用的配置项就是module.rules,而当前只需要简单配置解析.tsx文件类型即可
- 在
src/index.tsx中写入口文件
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import Test from '@components/Test'
const render = () => {
ReactDOM.render(
<div>1234</div>,
document.querySelector('#app')
)
}
render()
但是这时候你会发现有一个错误没有处理

这是因为在
tsconfig里面没有指定JSX的版本,这时候在tsconfig的compilerOptions中添加"jsx": "react"配置项即可消除错误
- 此外还需要注意一点,以后需要
import xxx from 'xxx'这样的文件的话需要在webpack中的resolve项中配置extensions,这样以后引入文件就不需要带扩展名
module.exports = {
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
}
}
- 添加页面模板
在
public文件夹下新建文件夹tpl,然后在tpl中新建一个index.html,如下
mkdir public && cd public && touch index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
这时候有了页面模板还是不够的,还需要将页面模板和打包出来的
js文件关联起来,因为考虑到以后打包出来的js的文件不会是一个固定的名称,所以这里需要使用一个webpack的插件html-webpack-plugin
- 配置
html-webpack-plugin
module.exports = {
plugins: [
new HtmlwebpackPlugin({
template: 'public/index.html'
})
]
}
配置完成后就可以启动项目了
- 配置
tsconfig
- 编译目标 这时候我们切回
tsconfig配置中,会发现在compilerOptions配置项的target是es5,也就是说把ts代码编译成es5规范的代码,如果不做兼容的话,我们可以将它设置为es6,使其编译成es6的代码 - 模块处理 在
module项中,会发现生成的是commonjs的模块系统,因为不考虑兼容,所以这里我也将其设定为最新的esnext,并且将模块处理方式改为用node来处理,设置moduleResolution项为node,不做模块处理方式设置的话可能会有报错

- 项目启动
这时候我们可以在
package.json中添加启动命令
"dev": "webpack-dev-server --config build/webpack.config.js --mode development"
其中
--mode development用于指定开发模式,否则在webpack4+版本下会有警告 然后直接npm run dev即可
总结
其实这个时候项目其实就已经跑起来了,完全可以不用往下看,但是实际上的工作并没有做完,下一章就开始讲解如何提高开发体验
# 二、提升开发体验
本章主要介绍的是建立在项目初始化的基础上如何优化开发体验 内容包含如下:
- 支持
sass - 支持
css module - 配置公用的
sass属性 - 支持装饰器
- 路径优化
- 构建缓存
- 构建加速
# 2.1 支持sass
# 安装相应包
npm install -D node-sass sass-loader style-loader css-loader
webpack进行loader编译的顺序是从下到上的:知道上面的顺序后我们在webpack中的配置就非常简单了,直接在module.rules下面加上.scss文件类型的编译配置即可

查看效果,这时候我们在
src下面新建一个index.scss,然后在index.tsx里面引入这个文件查看

# 2.2 支持css module
css module是针对css类名作用域做出限定的一种规范,用以解决css类名冲突的问题
- 安装对应的包 因为在这里我们用的是
TypeScript,所以可以用typings-for-css-modules-loader这个包,这个包也可以替代css-loader的功能,此外这个包还能根据.scss文件里面的类名自动生成对应的.d.ts文件
npm install -D typings-for-css-modules-loader
配置
webpack这个配置接非常简单了,因为要用typings-for-css-modules-loader替代css-loader的功能,所以直接替换即可,将前面sass的配置修改为如下:

修改为这样既可,但是同时我们也发现一个问题:

- 这个问题导致的原因是因为
.scss文件中并没有类似export这样的关键词用于导出一个模块,所以也就导致报错找不到模块,这个问题可以通过ts的模块声明(declare module)来解决。 - 解决模块声明问题,这时候我们在根目录下新建一个
typings文件夹,用于存放.scss的模块声明,以及后续需要用到的全局校验接口,然后新建typed-css-modules.d.ts文件用于存放.scss模块声明,目录结构和声明内容如下

这个时候回到
index.tsx文件中你会发现错误标红消失了,然后我们在index.scss文件中新增如下代码

保存后你会发现当前目录下新增了一个
index.scss.d.ts文件,打开里面可以发现是针对每个类名的类型校验,当以后新增类名的时候,typed-css-modules.d.ts都会自动在index.scss.d.ts里面新增对应的类型校验

这时候回到页面查看,你会发现类名变成了一个hash值,这样可以有效地避免类名全局污染问题

# 2.3 配置公共sass属性
既然已经可以使用
sass进行更加简便的css代码编写,那么我们也可以将常用的一些样式代码和sass变量写入公共文件中,当使用的时候就可以直接引入使用,这可以提高一定的效率节约时间
- 新建公共样式目录
首先在
src目录下新建styles文件夹,然后在styles文件夹下新建var.scss文件用于存放样式变量。 之后在var.scss文件里写入一个颜色变量和一个样式:

- 查看效果
然后在
index.scss文件里面引入var.scss,接着就可以直接使用里面的变量了

- 优化
上面的效果其实已经达成,但还是存在一个不好的问题,就是在引入
var.scss的路径上要根据每个文件夹的路径相对来引入非常麻烦,那么我们能否做到只需要@import var.scss就行呢?答案是可以的,我们可以使用一个node-sass的属性includePaths进行路径优化:

# 2.4 支持装饰器
前置工作 在
src目录下新建一个components文件夹,用于存放通用组件,然后在components文件及里面新建一个组件Test,然后在网页入口引入这个组件,如下图所示:


什么是装饰器,为什么需要装饰器 装饰器本质上就是一个函数,这个函数对类(
class)本身进行一些处理,也可以将装饰器的写法当做一种语法糖,如果不用装饰器的话,可以写成下图这样

设置装饰器可用 根据装饰器的语法,我们可以将上面的代码写成如下:

但是你会发现这里报了一个错误,这是因为装饰器语法在
es6标准中还只是一个提案,并未正式支持,但是在ts中,装饰器已经被正式支持了,不用ts的可以自行安装babel相关包进行支持

那么怎么解决这个错误呢?我们根据错误提示进入到
tsconfig文件中,将experimentalDecorators设置为true即可,然后回到页面查看log装饰器已经生效了
# 2.5 优化路径
在上面的例子中我们新建了
components文件夹,然后在入口处引入了其中的Test组件
但是这时候需要考虑到一个问题,如果以后在一个层级比较深的文件中引入这个组件会不会产生如下这种情况呢?
import Test from '../../../../components/Test'
这样不仅书写起来麻烦还容易出错,因此这时候就需要进行一些路径上的优化,使得无论在哪个地方引入这些组件都能用同一种写法,例如:
import Test from '@comonents/Test'
这里针对路径的优化有两种方案,第一种是直接在
webpack.resolve.alias中进行路径配置:



接着我们就可以愉快地使用简化后的路径了:

# 2.6 构建缓存





