react-router-dom-4.3.*
TypeScript-3.5.*
webpack-4.*
eslint-5.16.*
项目目录
├── dist # 打包结果目录 │ ├── demo1 //类别demo1的打包结果 │ │ ├── demo1.himl │ │ ├── demo1.js │ │ └── demo1.css │ └── demo2 ... //类别demo2的打包结果 ├── src # 业务资源文件目录 │ ├── category //项目分类 │ │ ├── demo1 │ │ ├── demo2 │ │ └── ... │ ├── components //公共组件 │ ├── util //公共资源 │ └── custom.d.ts //项目全局变量声明文件 ├── index.html //项目启动入口 ├── .gitignore //git忽略文件 ├── .eslintrc.js //eslint校验配置 ├── package.json //依赖包 ├── tsconfig.json //ts配置 ├── webpack.config.build.js //webpack打包 ├── webpack.config.base.js //webpack基础配置 └── webpack.config.js //项目启动配置
前言
对于复杂或多人开发的 React 项目来说,管理和使用每个组件的 props 、 state 或许会成为一件让人头痛的事情,而为每一个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。
Typescript 给 React 带来很多好处:
在组件头部定义 interface,让每个人在拿到组件的第一时间就可以很明确知道该组件需要使用的 props 和 state;
在编译中发现问题,减少运行时的报错;
可以在编辑器中实现实时类型校验、引用查询;
约束类型,在混合多语言环境中降低风险,等。
需求
要搭建一个React+TypeScript+webpack的项目的话,一般都是团队开发多人多文件项目,在搭建之前需要优先考虑以下几个方面:
开发体验
项目打包
团队规范
安装
前置安装
首先需要全局安装typescript,这里默认大家都已经安装了node以及npm
npm install -g typescript
首先新建文件夹并进入
mkdir tsDemo && cd tsDemo
然后进行初始化,生成package.json和tsconfig.json
npm init -y && tsc --init
安装开发工具
npm install-D webpack webpack-cli webpack-dev-server
安装react相关
因为需要整合ts,而react原本的包是不包含验证包的,所以这里也需要安装相关ts验证包
npm install -S react react-dom npm install -D @types/react @types/react-dom
安装ts-loader
npm install -D ts-loader
以上是基本的 后续会贴出项目demo里面包含所有依赖包
webpack配置
添加webpack文件
根目录下新建webpack.config.base.js、webpack.config.build.js、webpack.config.js文件
touch webpack.config.base.js webpack.config.build.js webpack.config.js
entry:入口文件(你要打包,就告诉我打包哪些)
output:出口文件(我打包完了,给你放到哪里)
resolve: 寻找模块所对应的文件
module:模块(放lorder,编译浏览器不认识的东西)
plugins:插件(辅助开发,提高开发效率)
externals:打包忽略
devServer:服务器(webpack提供的本地服务器)
mode:模式,分为开发模式、生产模式。此为4.X里新增的
配置entry入口文件
因为大部分项目是多入口,多类别的,所有入口配置时不要配置单一入口
const fs = require("fs"); const path = require("path"); const optimist = require("optimist"); const cateName = optimist.argv.cate; let entryObj = {}; const srcPath = `${__dirname}/src`; //获取当前项目要启动或者打包的基础路径 const entryPath = `${srcPath}/category/`; //未指定类别 启动或者打包所有类别 //如:npm run dev 或者npm run build if (cateName == true) { fs.readdirSync(entryPath).forEach((cateName, index) => { // cateName/cateName指定输出路径为entryname if (cateName != "index.html" && cateName != ".DS_Store") entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`; }); } else if (cateName.indexOf(",")) { // 一次指定多个类别 类别之间以","分割 //如:npm run dev erhsouche,huoche let cateNameArray = cateName.split(","); for (let i = 0; i < cateNameArray.length; i++) { entryObj[`${cateNameArray[i]}/${cateNameArray[i]}`] = `${entryPath + cateNameArray[i]}/${ cateNameArray[i] }.tsx`; } } else { // 打包单个入口文件 //如:npm run dev ershouche entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`; } const webpackConfig = { entry: entryObj, } module.exports = { webpackConfig, entryObj };
配置output出口文件