react17+ts+umi构建移动端web项目
# 一、使用umi创建初始项目
# 1. 找个位置创建项目空目录
$ mkdir projectName && cd projectName
# 2. 通过官方工具创建项目
$ yarn create @umijs/umi-app
# 3. 安装依赖
$ yarn
# 4. 启动项目
$ yarn start
# 二、移动端适配
# 1. 安装postcss-px-to-viewport
插件,将px自动转换为vw
$ yarn add postcss-px-to-viewport -D
# 2. 在.umirc.ts
文件中增加配置
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [{ path: '/', component: '@/pages/index' }],
fastRefresh: {},
antd: {
mobile: false,
},
extraPostCSSPlugins: [
// 使用require直接引入
require('postcss-px-to-viewport')({
unitToConvert: 'px', // 需要转换的单位,默认为"px"
viewportWidth: 750, // 设计稿的视窗宽度
unitPrecision: 5, // 单位转换后保留的精度
propList: ['*'], // 能转化为 vw 的属性列表
viewportUnit: 'vw', // 希望使用的视窗单位
fontViewportUnit: 'vw', // 字体使用的视窗单位
selectorBlackList: ['ignore-', 'adm-'], // 需要忽略的 CSS 选择器,不会转为视窗单位,使用原有的 px 等单位
minPixelValue: 1, // 设置最小的转换数值,如果为 1 的话,只有大于 1 的值会被转换
mediaQuery: false, // 媒体查询里的单位是否需要转换单位
replace: true, // 是否直接更换属性值,而不添加备用属性
exclude: [], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: /\/src\//, // 如果设置了include,那将只有匹配到的文件才会被转换
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件
landscapeUnit: 'vw', // 横屏时使用的单位
landscapeWidth: 1125, // 横屏时使用的视窗宽度
}),
],
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 3. 首页测试一下是否生效
# 四、初始化CSS代码
建站老手都知道,这是为了考虑到浏览器的兼容问题,其实不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面差异。当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。 最简单的初始化方法就是: * {padding: 0; margin: 0;} 。有很多人也是这样写的。这确实很简单,但有人就会感到疑问:*号这样一个通用符在编写代码的时候是快,但如果网站很大,CSS样式表文件很大,这样写的话,他会把所有的标签都初始化一遍,这样就大大的加强了网站运行的负载,会使网站加载的时候需要很长一段时间。 CSS初始化是指重设浏览器的样式。不同的浏览器默认的样式可能不尽相同,所以开发时的第一件事可能就是如何把它们统一。如果没对CSS初始化往往会出现浏览器之间的页面差异。每次新开发网站或新网页时候通过初始化CSS样式的属性,为我们将用到的CSS或html标签更加方便准确,使得我们开发网页内容时更加方便简洁,同时减少CSS代码量,节约网页下载时间。
# 1. 在/src/global.less
中设置初始化CSS代码
body,
ol,
ul,
h1,
h2,
h3,
h4,
h5,
h6,
p,
th,
td,
dl,
dd,
form,
fieldset,
legend,
input,
textarea,
select,
figure,
figcaption {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
border: none;
}
input {
outline: none;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 五、常用TypeScript Props类型
# 1. 常用基础类型
type AppProps = {
message: string
count: number
disabled: boolean
/** array of a type! */
names: string[]
/** string literals to specify exact string values, with a union type to join them together */
status: 'waiting' | 'success'
/** 任意需要使用其属性的对象(不推荐使用,但是作为占位很有用) */
obj: object
/** 作用和`object`几乎一样,和 `Object`完全一样 */
obj2: {}
/** 列出对象全部数量的属性 (推荐使用) */
obj3: {
id: string
title: string
}
/** array of objects! (common) */
objArr: {
id: string
title: string
}[]
/** 任意数量属性的字典,具有相同类型*/
dict1: {
[key: string]: MyTypeHere
}
/** 作用和dict1完全相同 */
dict2: Record<string, MyTypeHere>
/** 任意完全不会调用的函数 */
onSomething: Function
/** 没有参数&返回值的函数 */
onClick: () => void
/** 携带参数的函数 */
onChange: (id: number) => void
/** 携带点击事件的函数 */
onClick(event: React.MouseEvent<HTMLButtonElement>): void
/** 可选的属性 */
optional?: OptionalType
/** className */
className: React.HTMLAttributes<HTMLDivElement>
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 2. 常用React属性类型
export declare interface AppBetterProps {
children: React.ReactNode // 一般情况下推荐使用,支持所有类型 Great
functionChildren: (name: string) => React.ReactNode
style?: React.CSSProperties // 传递style对象
onChange?: React.FormEventHandler<HTMLInputElement>
}
export declare interface AppProps {
children1: JSX.Element // 差, 不支持数组
children2: JSX.Element | JSX.Element[] // 一般, 不支持字符串
children3: React.ReactChildren // 忽略命名,不是一个合适的类型,工具类类型
children4: React.ReactChild[] // 很好
children: React.ReactNode // 最佳,支持所有类型 推荐使用
functionChildren: (name: string) => React.ReactNode // recommended function as a child render prop type
style?: React.CSSProperties // 传递style对象
onChange?: React.FormEventHandler<HTMLInputElement> // 表单事件, 泛型参数是event.target的类型
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 六、配置 prettier,eslint, stylelint
umi 维护了一个 prettier,eslint,stylelint 的配置文件合集 umi-fabric (opens new window)
根目录新建下面三个文件,删除.prettierrc文件
.eslintrc.js
、.prettierrc.js
、.stylelintrc.js
# 配置如下
//.eslintrc.js 配置
module.exports = {
extends: [require.resolve('@umijs/fabric/dist/eslint')],
// in antd-design-pro
globals: {
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,
page: true,
},
rules: {
// your rules
'prefer-const': 0,
},
};
//.prettierrc.js 配置
const fabric = require('@umijs/fabric')
module.exports = {
...fabric.prettier,
semi: false,
}
//.stylelintrc.js 配置
const fabric = require('@umijs/fabric')
module.exports = {
...fabric.stylelint,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
根目录新建eslint忽略文件 .eslintignore
.eslintrc.js
node_modules
2
在package.json
里面的lint-staged
新增 "eslint --fix"
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write",
"eslint --fix"
]
},
2
3
4
5
6
7
8
9
VSCode安装插件
# 六、多环境配置
# 1. 配置文件
Umi 在 .umirc.ts
或 config/config.ts
中配置项目和插件,支持 es6。
如果项目的配置不复杂,推荐在 .umirc.ts
中写配置; 如果项目的配置比较复杂,可以将配置写在 config/config.ts
中,并把配置的一部分拆分出去,比如路由配置可以拆分成单独的 routes.ts
推荐两种配置方式二选一,.umirc.ts
优先级更高。
我们采用config的方式,删除.umirc.ts
,根目录新建config文件夹,
在里面新建config.ts
默认内容如下
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/', component: '@/pages/index' },
],
fastRefresh: {},
});
2
3
4
5
6
7
8
9
10
11
12
# 2. 多环境多配置文件
可以通过环境变量 UMI_ENV
区分不同环境来指定配置。
为了兼容性,可借助三方工具 cross-env
来设置环境变量
yarn add cross-env --dev
在package.json
中的script
中
"start": "cross-env UMI_ENV=dev umi dev",
"start:test": "cross-env UMI_ENV=test umi dev",
"start:prd": "cross-env UMI_ENV=prd umi dev",
"build": "cross-env UMI_ENV=dev umi build",
"build:test": "cross-env UMI_ENV=test umi build",
"build:prd": "cross-env UMI_ENV=prd umi build",
2
3
4
5
6
然后再config文件夹下 新建
config.dev.ts
,config.test.ts
,config.prd.ts
代表开发环境,测试环境,生产环境的配置文件.
config.dev.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'dev',
},
});
2
3
4
5
6
config.test.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'test',
},
});
2
3
4
5
6
config.prd.ts
import { defineConfig } from 'umi';
export default defineConfig({
define: {
CurrentEnvironment: 'prd',
},
});
2
3
4
5
6
CurrentEnvironment
变量代表当前的环境,后面根据不同的环境配置不同的请求地址会用到
define
用于提供给代码中可用的变量,定义的变量可以全局拿到
这时 执行 yarn start:prd
,然后去到pages的index.tsx
打印CurrentEnvironment
.
这时需要去到根目录的 typings.d.ts
添加
/ 声明当前的环境
declare const CurrentEnvironment: 'dev' | 'test' | 'prd';
2
config.ts作为配置文件时,记得删除.umirc.ts 不然config.ts不会生效。