上一篇介绍完 HMR 热更新之后,接着我们会讲解 React 项目搭建。
题外话
首先官方提供了一个 create-react-app 脚手架工具来创建 React 项目。
*本项目不采用该脚手架进行搭建。
*下面使用 npm 举例,与 yarn 大同小异。
*仅简述,不感兴趣可跳过该内容。
# 安装 create-react-app
$ npm install -g create-react-app
# 创建项目
$ create-react-app your_project
# 打开项目
$ cd your_project
# 运行项目
$ npm run start
# 项目打包
$ npm run build
# 自定义配置,注意执行这个命令是不可逆的
$ npm run eject
我们通过
create-react-app
创建的项目,可以看到它只有react
、react-dom
、react-scripts
等少数依赖。其实,它将webpack
、Babel
、ESLint
等依赖包通过creat-react-app
封装到了react-scripts
当中,包括基本启动命令都是通过调用react-scripts
这个依赖下面的命令来完成的。除了
start
、build
、test
命令。它还有一个"eject": "react-scripts eject"
命令。它的作用是什么呢?它会将原本
creat-react-app
对webpack
、Babel
、ESLint
等相关配置的封装“弹出”。假如我们要将creat-react-app
配置文件进行修改,现有目录下是没有地方修改的。此时,我们就可以通过npm run eject
命令将原本被封装到脚手架当中的命令弹射出来,然后在项目目录下看到很多配置文件。注意,该命令是单向操作,不可逆。(在README.md
中对此命令有简述。)
使用 Babel
Babel 是什么?
Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面列出的是 Babel 能为你做的事情:
- 语法转换
- 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块,babel 7.4 开始废弃
@babel/polyfill
)- 源码转换 (codemods)
- 更多! (查看这些 视频 获得启发)
babel 配置
- 安装依赖
$ yarn add --dev babel-loader@8.0.6 @babel-core/core@7.7.4
- 添加
module.rules
配置
// webpack.config.js
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
- 创建
.babelrc
配置文件
我们已经配置了 Babel,但实际上并未做任何事情。在项目根目录中创建一个.babelrc
配置文件(JSON),并启用一些预设和插件。
-
@babel/preset-env:解析 ES6 语法,它只做语法转换,如
const
、let
。它并不处理includes
、Promise
等 api。 - @babel/preset-react:解析 JSX 语法。
- @babel/plugin-transform-runtime:解决全局变量污染,以及重复声明 helper 函数的问题。
$ yarn add --dev @babel/preset-env@7.7.4
$ yarn add --dev @babel/preset-react@7.7.4
$ yarn add --dev @babel/plugin-transform-runtime@7.7.4
$ yarn add --dev core-js@3.6.0
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"modules": false, // 将 ESM 转化为其他模块规范,默认值 false。
"useBuiltIns": "usage", // 按需加载
"corejs": 3, // Babel 建议使用 useBuiltIns 选项时显式设置 core-js 版本
"debug": false // 打印插件使用情况
}
],
"@babel/preset-react" // 解析 JSX 语法
],
"plugins": ["@babel/plugin-transform-runtime"]
}
*关于 .babelrc
相关预设与插件详解,在后续会专门出一篇文章整理介绍;
*顺序问题:1 Plugins 在 Presets 前运行;2 Plugins 按照声明次序顺序执行;3 Presets 按照声明次序逆序执行。
React
- 首先安装
react
、react-dom
依赖包。
$ yarn add react@16.12.0 react-dom@16.12.0
插个话题:为什么 react 和 react-dom 要分成两个包?
对于具有跨平台能力的 React 体系来说,分包可以将抽象逻辑与平台实现分开。
- react 包即是抽象逻辑,它包含了 React 的主干逻辑。例如组件实现、更新调度等。
- react-dom 顾名思义就是一种针对 dom 的平台实现,主要用于在 web 端进行渲染。而声名在外的 React Native 则是原生应用实现,可以通过 React Native 内部的相应机制与操作系统进行通信来调用原生控件进行渲染。
*以上简述来自知乎 Shockw4ver 回答。
- 引入 react
// index.js
import React from 'react'
import { render } from 'react-dom'
import './main.js'
import './style.css'
// 最简单的 React 示例
const rootElem = document.getElementById('app')
render(<div>Hello React!</div>, rootElem)
if(module.hot) {
module.hot.accept('./main.js', () => {
console.log('Accept update!')
})
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
至此,最简单的 React 示例已经成功了。
接下来,我们将会先介绍接入 react-hot-loader
实现 react 的局部刷新问题。
最后附上
// package.json
{
"name": "webpack4_demo",
"version": "1.0.0",
"description": "从零到一搭建 react 项目",
"main": "src/index.js",
"repository": "git@github.com:toFrankie/webpack4_demo.git",
"author": "Frankie <1426203851@qq.com>",
"license": "MIT",
"private": true,
"scripts": {
"dev": "webpack-dev-server --config webpack.config.js --colors",
"build": "webpack --config webpack.config.js --progress --colors --mode=production"
},
"dependencies": {
"react": "16.12.0",
"react-dom": "16.12.0",
"webpack": "4.41.2",
"webpack-cli": "3.3.10"
},
"devDependencies": {
"@babel/core": "7.7.4",
"@babel/plugin-transform-runtime": "7.7.4",
"@babel/preset-env": "7.7.4",
"@babel/preset-react": "7.7.4",
"babel-loader": "8.0.6",
"clean-webpack-plugin": "3.0.0",
"core-js": "3.6.0",
"css-loader": "3.2.0",
"html-webpack-plugin": "3.2.0",
"style-loader": "1.0.0",
"webpack-dev-server": "3.9.0"
}
}
网友评论