create-react-app使用笔记
官方脚手架功能强大,各个需求点也是考虑到了,是开发react应用的神器。
###如何使用
create-react-app
依赖两个包,一个是create-react-app
全局命令工具包,用来创建新的项目,就是create-react-app myProject
命令;第二个是react-scripts
在生成的项目中依赖的包。一般不用升级create-react-app,因为主要的react依赖都是由react-scripts来生成的,而生成的react-scripts
会自动下载最新 版,所以你用的react包也是最新版本的。
###create-react-app生成的项目结构
|
|
项目中必须存在的文件:
- public/index.html html模版文件
- src/index.js react应用的入口文件
可以在src
目录下新建N多个子集目录,只有在src下的资源,才能被webpack处理,所以一般都将js和css资源放入src
目录下,图片资源也可以放src
里面,
官方demo则将svg资源放入了src
中。
可运行的脚本
npm start
运行开发运行,默认会打开http://localhost:3000
的浏览界,可以热更新代码npm test
运行测试脚本npm run build
打包命令,会启用react的生产环境模式,去除类型检查等,压缩代码npm run eject
暴露出默认配置文件
###支持最新的JavaScript新功能和Polyfills
该项目支持最新的JavaScript标准的超集。除了es6的语法,create-react-app
还支持:
- 指数运算符
- Async/await语法(ES2017)
- 对象的解构赋值
- 动态import 语法
- 类静态属性
- JSX语法和flow语法
另外官方仅仅包含了很少一个部分的ES6 polyfills:
- Object.assign() 支持 object-assign
- Promise 支持,promise
- fetch支持,whatwg-fetch
所以当用到一些需要polyfills的功能时,某些polyfills需要手动添加
###改变html的title
找到public/index.html
直接修改title即可,如果是单页应用,则在每个component的componentDidMount的生命周期方法中,调用document.title来修改。你也可以参考React Helmet
###导入组件
支持commonjs模块语法,当然最好使用import 和 export 语法
###代码分割
当某些代码片段需要异步加载的时候特别有用,用法如下:
chart.js
|
|
App.js
|
|
也可以使用async/await
语法来使用这个特性:
App.js
|
|
比用上面的语法简单清晰很多。
###添加样式表
create-react-app
已经内置了配置好了的webpack,可以将css当作js资源一样引入到js文件中。
Button.css
|
|
Button.js
|
|
在开发环境中,修改css文件,可以热更新;生产环境中,则所有css文件会被打包进一个.css文件中,通过link标签注入到public/index.html
中。这种方式,增加了迁移到其他打包工具的成本,不过对于打包工具仅仅是webpack来说很方便。
另外create-react-app
集成了插件Autoprefixer
,可以自动帮你补全浏览器前缀。
###添加图像、字体、文件
引入一个文件,是告诉webpack把,这个文件引入到打包的bundle中,不像import css文件,引入一个文件,webpack会自动转化为一个字符串,如,src的url地址,href的超链接地址。
比如图片的话,如果大小小雨10,000字节,则会返回一个data URI的字符串,如果大于的话,则返回相对于%PUBLIC_URL%
的url地址。目前create-react-app
支持bmp,gif,jpg,jpeg,png。
|
|
webpack会根据资源的内容动态生成hash,如果以后图片有小修改,就不用加版本号了,清除缓存很方便。
###正确使用public
文件夹
public/index.html
里面的内容可以随意修改,添加或者删除script标签等。
create-react-app
鼓励使用import 语法来引入 样式、图片、字体文件,因为有如下好处:
- 一起打包可以减少网络请求
- 编译过程中的错误,可以预防上线出现的404错误
- 根据内容自动生成hash,可以预防浏览器缓存
如果将静态资源放入public
文件夹中,它不会被webpack处理,仅仅打包之后,会被拷贝到build
目录中。为了引用到这个资源,你需要使用一个叫PUBLIC_URL
的变量。在index.html
中,有如下代码:
|
|
只有在public
中的文件,才可以用%PUBLIC_URL%
获取。如果资源在src或者node_modules里面,你需要拷贝到public
目录中去使用。
当我们使用yarn build
的时候,%PUBLIC_URL%
会被绝对路径替换,就是网站的静态资源根目录。
在JavaScript代码中,也可以通过process.env.PUBLIC_URL
来访问,不过官方不推荐使用。
|
|
需要注意的是:
public
里的文件不会被预处理,和压缩- 丢失文件,会导致404
- 当文件改变时,需要手动重命名,或者手动添加版本号,来处理缓存问题。
什么时候使用public
文件夹
- 需要在构建输出中具有特定名称的文件,比如manifest.webmanifest
- 有N多图片,动态引入的图片
- 某个js文件不想引入到bundle中
- 一些第三方库和webpack不兼容
###如何使用全局变量
当在js代码中引入第三方的全局变量时,linter会提示,没有定义过的变量,怎么解决?
|
|
or
|
|
不检测当行代码
自动格式化代码
prettier是一个独立的(opinionated)代码格式化工具。用它,可以确保在一个工程里有统一的代码风格。使用方法:
|
|
或者( 通过yarn安装有坑,下面会讲解 )
|
|
husky
监听hithooks的事件,然后执行自定义的命令lint-staged
允许我们在git中已经暂存的文件里,执行脚本命令prettier
在commit之前,格式化我们的代码
修改package.json
文件:
|
|
|
|
现在,当我们git commit -m "..."
执行的时候,Prettier
会自动格式化已经修改过的文件,然后提交。
当然,我们也可以通过./node_modules/.bin/prettier --single-quote --write "src/**/*.{js,jsx}"
来格式化整个工程。
通过yarn
安装之后,可能会遇到git commit
之后没有任何反应的坑,google之后,发现how to setting up?
情况一样,原来通过yarn
安装的husky
,默认不会执行husky的安装程序。所以解决方案就是手动执行一下安装程序。
|
|
看到done,就说明设置git的钩子成功了
在Visual Studio Code中Debugger
首先需要安装最新的VS Code和 VS Code Chrome Debugger Extension 。
之后在项目根目录下新建.vscode
文件夹,在里面新建launch.json
,将如下代码放入其中:
|
|
注意⚠️:如果自定义修改了HOST或者PORT,则需要修改相应的地址
配置好了之后,启动yarn start
,在VS Code
中按F5
或者按绿色的debug按钮进行debug。
自定义环境变量
环境变量,可以很方便的,根据某些条件,展示不同的数据,比如(根据环境,判断是否需要mock数据);或者使用一些不在版本控制力的敏感信息;因为是在构建期间运行,所以webpack可以直接进行一些逻辑的判断,不会出现的代码直接会删除,不会进入打包文件。
在项目工程中,可以使用自定义的环境变量,就像声明在js文件的普通变量一样。默认的,内置了一个NODE_ENV
环境变量,其他的环境变量,规定必须要以REACT_APP_
开头,以防止和其他环境变量冲突。
环境变量可以只能在构建期间使用,不能在生产环境中动态使用。如果需要动态获取的话,需要服务器端支持。
环境变量是定义在process.env
对象上的,比如,定义了一个REACT_APP_SECRET_CODE
变量,需要在js文件中使用的话,需要用process.env.REACT_APP_SECRET_CODE
来获取。
要获取当前的开发环境,使用:
|
|
npm start
启动的话,这个值永远为development
npm test
启动的话,这个值永远为test
npm run build
启动的话,这个值永远为production
NODE_ENV
这个环境变量,不允许手动修改,即使修改了也不会生效。
js中使用
|
|
public/index.html
中使用:
|
|
注意⚠️:
- 除了NODE_ENV和PUBLIC_URL连个环境变量,其他环境变量都需要由REACTAPP开头。
- 环境变量只有在构建期间有效,运行期间无效。
有两种方式定义环境变量:
shell命令
- windows:
set REACT_APP_SECRET_CODE=abcdef&&npm start
- Linux,maxOs:
REACT_APP_SECRET_CODE=abcdef npm start
这种方式,环境变量只有在shell回话中有效
- windows:
.env
文件为了永久的使用环境变量,需要在根目录中新建一个
.env
文件.env:
1REACT_APP_SECRET_CODE=abcdef.env文件可以添加进版本控制中(
.gitignore
中配置.env*.local
)。还有一些其他的文件:
.env
:默认.env.local
:本地覆盖,这个在除了test构建,其他所有构建中都有效.env.development
,.env.test
,.env.production
:指定构建环境中有效.env.development.local
,.env.test.local
,.env.production.local
:本地覆盖指定构建环境
这些定义的优先级( 越靠近左边的,优先级越高 ):
npm start
:.env.development.local
,.env.development
,.env.local
,.env
npm run build
:.env.production.local
,.env.production
,.env.local
,.env
npm test
:.env.test.local
,.env.test
,.env
(注意⚠️:没有.env.local
)
能否使用修饰器
不能。
- 这是一个试验性的建议,可能会改变。
- 目前的规格版本没有得到Babel官方的支持。
- 如果规范发生变化,将无法编写重构件codemod,因为Facebook内部使用它们。
如果需要使用,可以使用npm run eject
自己用第三方工具配置
开发环境中转发API请求
一般生产环境的项目都有如下特征:
|
|
为了告诉开发服务器,如何重定向一个未知的接口请求,需要在package.json
中添加proxy
字段,比如:
|
|
当我们发起请求,比如fetch('/api/todos')
,开发服务器首先确认,当前不是一个静态资源,之后会转发这个请求到http://localhost:8080/api/todos
,开发服务器只会尝试转发Accept
头部不是text/html
的请求。
转发请求可以避免跨域请求失败:
Fetch API cannot load http://localhost:8080/api/todos. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
可以扩展proxy
:
自定义代理请求
修改
package.json
1234567891011{// ..."proxy": {"/api": {"target": "<url>","ws": true// ...}}// ...}所有的
/api
开头的请求都会被代理,包括头部Accept
是text/html
的请求,和默认的配置proxy
不一样。- 12345678910111213141516171819202122232425262728293031{// ..."proxy": {// 代理以 /api 开头的请求"/api": {"target": "<url_1>","ws": true// ...},// 代理以 /foo 开头的请求"/foo": {"target": "<url_2>","ssl": true,"pathRewrite": { // 接口重写"^/foo": "/foo/beta"}// ...},// 代理 /bar/abc.html 而不是 /bar/sub/def.html"/bar/[^/]*[.]html": {"target": "<url_3>",// ...},// 代理 /baz/abc.html 和 /baz/sub/def.html"/baz/.*/.*[.]html": {"target": "<url_4>"// ...}}// ...}
支持WebSocket的代理
12345678910111213{// ..."proxy": {"/socket": {// 代理的目标websocket服务器"target": "ws://<socket_url>",// 标记这是webSocket请求"ws": true// ...}}// ...}
启动HTTPS
- Windows:
set HTTPS=true&&npm start
- Linux,macOS:
HTTPS=true npm start
在单独的环境中(隔离)开发组件
通常,在一个应用程序中,你有很多的UI组件,而且每个组件都有很多不同的状态。 例如,一个简单的按钮组件可能具有以下状态:
- 正常的状态下,仅展示文本标签。
- 有禁用的模式
- 有一个loading状态
通常,如果不单独跑各个状态的组件,很难一次性看到这些状态。
create-react-app
不包含这些开发工具,需要使用第三方插件,来实现同时查看一个组件的所有状态。工具有:
-
首先,全局安装
@storybook/cli
:1npm install -g @storybook/cli之后,在根目录执行:
1getstorybook之后会自动安装以来:
1234567891011121314151617181920212223➜ testReact git:(master) ✗ getstorybookgetstorybook - the simplest way to add a storybook to your project.• Detecting project type. ✓• Adding storybook support to your "Create React App" based project. ✓• Preparing to install dependencies. ✓yarn install v1.2.1[1/4] 🔍 Resolving packages...[2/4] 🚚 Fetching packages...[3/4] 🔗 Linking dependencies.......✨ Done in 21.32s.• Installing dependencies. ✓To run your storybook, type:yarn run storybookFor more information visit: https://storybook.js.org提示你可以通过
yarn run storybook
来启动storybook
。
这些工具可以单独部署,这样子团队中的其他人就可以直接查看组件的各个状态,而不需要启动服务器。
默认支持渐进式Web应用
create-react-app
创建的项目默认就会支持 [渐进式web应用(PWA)] ,会使用 service workers 实现 缓存优先策略 来优化用户再次访问应用的速度。什么是service workers?
当然,你也可以通过设置默认不开启这个特性,但是如果你在开发新的应用,推荐使用,特别在移动端Android设备上,能加速Web App的启动。
已缓存的项目,如果想禁用service-worker
,可以直接调用unregister
|
|
客户端路由
如果客户端使用的是HTML5的pushState history API
,许多静态资源文件请求将会失败。比如,请求页面/todos/42
,开发服务器会运行很好,但是生产环境将会失败。因为后台程序并没有配置/todos/42
这个路由,会返回404。
NODE的解决方案:
|
|
打包到相对路径
默认的create-react-app
会讲打包的默认路径设置为服务器的根目录/
。
要覆盖默认的设置,需要在package.json
中,设置homepage
:
|
|
设置之后,create-react-app
就知道了项目的根目录是:/index
。
之后生成的html文件:
|
|