create-react-app使用笔记

官方脚手架功能强大,各个需求点也是考虑到了,是开发react应用的神器。

1、如何使用

create-react-app依赖两个包,一个是create-react-app全局命令工具包,用来创建新的项目,就是create-react-app myProject命令;第二个是react-scripts在生成的项目中依赖的包。一般不用升级create-react-app,因为主要的react依赖都是由react-scripts来生成的,而生成的react-scripts会自动下载最新 版,所以你用的react包也是最新版本的。

2、create-react-app生成的项目结构

.
├── README.md
├── node_modules
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── registerServiceWorker.js
└── yarn.lock

项目中必须存在的文件:

  • public/index.html html模版文件
  • src/index.js react应用的入口文件

可以在src目录下新建N多个子集目录,只有在src下的资源,才能被webpack处理,所以一般都将js和css资源放入src目录下,图片资源也可以放src里面,

官方demo则将svg资源放入了src中。

3、支持最新的JavaScript新功能和Polyfills

该项目支持最新的JavaScript标准的超集。除了es6的语法,create-react-app还支持:

  • 指数运算符
  • Async/await语法(ES2017)
  • 对象的解构赋值
  • 动态import 语法
  • 类静态属性
  • JSX语法和flow语法

另外官方仅仅包含了很少一个部分的ES6 polyfills:

所以当用到一些需要polyfills的功能时,某些polyfills需要手动添加

4、改变html的title

找到public/index.html直接修改title即可,如果是单页应用,则在每个component的componentDidMount的生命周期方法中,调用document.title来修改。你也可以参考React Helmet

5、导入组件

支持commonjs模块语法,当然最好使用import 和 export 语法

6、代码分割

当某些代码片段需要异步加载的时候特别有用,用法如下:

chart.js

const initChart = () => { // do something... };

export { initChart };

App.js

import React, { Component } from 'react';

class App extends Component {
  click = () => {
    import('./chart.js')
      .then(({ initChart }) => {
        // 使用 initChart() ;
      })
      .catch(err => {
        // 错误处理
      });
  };

  render() {
    return (
      <div>
        <button onClick={this.click}>加载图表</button>
      </div>
    );
  }
}
export default App;

也可以使用async/await语法来使用这个特性:

App.js

import React, { Component } from 'react';

class App extends Component {
  click = async () => {
    let { initChart } = await import( './chart' ).catch( e=>console.warn(e) ) ;
    initChart() ;
  } ;
  render() {
    return (
      <div>
        <button onClick={this.click}>加载图表</button>
      </div>
    );
  }
}
export default App;

比用上面的语法简单清晰很多。

7、添加样式表

create-react-app已经内置了配置好了的webpack,可以将css当作js资源一样引入到js文件中。

Button.css

.Button { color: red ; }

Button.js

import React, { Component } from 'react';
import './Button.css'; // 引入css资源

class Button extends Component {
  render() {
    // 使用
    return <div className="Button" />;
  }
}

在开发环境中,修改css文件,可以热更新;生产环境中,则所有css文件会被打包进一个.css文件中,通过link标签注入到public/index.html中。这种方式,增加了迁移到其他打包工具的成本,不过对于打包工具仅仅是webpack来说很方便。

另外create-react-app集成了插件Autoprefixer,可以自动帮你补全浏览器前缀。

8、添加图像、字体、文件

引入一个文件,是告诉webpack把,这个文件引入到打包的bundle中,不像import css文件,引入一个文件,webpack会自动转化为一个字符串,如,src的url地址,href的超链接地址。

比如图片的话,如果大小小雨10,000字节,则会返回一个data URI的字符串,如果大于的话,则返回相对于%PUBLIC_URL%的url地址。目前create-react-app支持bmp,gif,jpg,jpeg,png。

import React from 'react';
import logo from './logo.png'; // 引入logo png资源
console.log(logo); // 字符串"/logo.84287d09.png"
function Header() {
  // 设置src等于logo
  return <img src={logo} alt="Logo" />;
}
export default Header;

webpack会根据资源的内容动态生成hash,如果以后图片有小修改,就不用加版本号了,清除缓存很方便。

9、正确使用public文件夹

public/index.html里面的内容可以随意修改,添加或者删除script标签等。

create-react-app鼓励使用import 语法来引入 样式、图片、字体文件,因为有如下好处:

  • 一起打包可以减少网络请求
  • 编译过程中的错误,可以预防上线出现的404错误
  • 根据内容自动生成hash,可以预防浏览器缓存

如果将静态资源放入public文件夹中,它不会被webpack处理,仅仅打包之后,会被拷贝到build目录中。为了引用到这个资源,你需要使用一个叫PUBLIC_URL的变量。在index.html中,有如下代码:

<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

只有在public中的文件,才可以用%PUBLIC_URL%获取。如果资源在src或者node_modules里面,你需要拷贝到public目录中去使用。

当我们使用yarn build的时候,%PUBLIC_URL%会被绝对路径替换,就是网站的静态资源根目录。

在JavaScript代码中,也可以通过process.env.PUBLIC_URL来访问,不过官方不推荐使用。

render() {
  return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}

需要注意的是:

  • public里的文件不会被预处理,和压缩
  • 丢失文件,会导致404
  • 当文件改变时,需要手动重命名,或者手动添加版本号,来处理缓存问题。

什么时候使用public文件夹

  • 需要在构建输出中具有特定名称的文件,比如manifest.webmanifest
  • 有N多图片,动态引入的图片
  • 某个js文件不想引入到bundle中
  • 一些第三方库和webpack不兼容

10、如何使用全局变量

当在js代码中引入第三方的全局变量时,linter会提示,没有定义过的变量,怎么解决?

const $ = window.$

or

$.extend( {} , {a:1} ) ; // eslint-disable-line

不检测当行代码

本文来自网易实践者社区,经作者毛庭峰授权发布。