1.3 分解React应用
前面我们提到过,React应用实际上依赖于一个很大很复杂的技术栈,我们使用create-react-app避免在一开始就费太多精力配置技术栈,不过现在是时候了解一下这个技术栈了。
我们启动React应用的命令是npm start,看一看package.json中对start脚本的定义,如下所示:
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }
可以看到,start命令实际上是调用了react-scripts这个命令,react-scripts是create-react-app添加的一个npm包,所有的配置文件都藏在node_modules/react-scripts目录下,我们当然可以钻进这个目录去一探究竟,但是也可以使用eject方法来看清楚背后的原理。
你可以发现package.json文件中和start并列还有其他几个命令,其中build可以创建生产环境优化代码,test用于单元测试,还有一个eject命令很有意思。
这个eject(弹射)命令做的事情,就是把潜藏在react-scripts中的一系列技术栈配置都“弹射”到应用的顶层,然后我们就可以研究这些配置细节了,而且可以更灵活地定制应用的配置。
注意
eject命令是不可逆的,就好像战斗机飞行员选择“弹射”出驾驶舱,等于是放弃了这架战斗机,是不可能再飞回驾驶舱的。所以,当你执行eject之前,最好做一下备份。
我们在命令行下执行下面的命令,完成“弹射”操作:
npm run eject
这个命令会让改变一些文件,也会添加一些文件。
当前目录下会增加两个目录,一个是scripts,另一个是config,同时,package.json文件中的scripts部分也发生了变化:
"scripts": { "start": "node scripts/start.js", "build": "node scripts/build.js", "test": "node scripts/test.js --env=jsdom" },
从此之后,start脚本将使用scripts目录下的start.js,而不是node_modules目录下的react-scripts,弹射成功,再也回不去了。
在config目录下的webpack.config.dev.js文件,定制的就是npm start所做的构造过程,其中有一段关于babel的定义:
{ test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', query: { // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true } },
代码中paths.appSrc的值就是src,所以这段配置的含义指的是所有以js或者jsx为扩展名的文件,都会由babel所处理。
并不是所有的浏览器都支持所有ES6语法,但是有了babel,我们就可以不用顾忌太多,因为babel会把ES6语法的JavaScript代码转译(transpile)成浏览器普遍支持的JavaScript代码,实际上,在React的社区中,不使用ES6语法写代码才显得奇怪。