作为一个「全干」程序员,前端相关的工作是少不了的。JavaScript 作为前端开发的不二语言,生态比较繁荣。Vue 和 React 就是其中比较有代表性的两个选择。一直以来我使用 Vue 比较多,所以对 React 还不是很了解。最近趁着一个项目前端要重构的机会,准备尝试一下 React。
开始之前的想法
在本地体验 React 最简单的方式就是去官网下载打包好的源码,然后通过 <script>
引入几个 React 的基础库到 HTML 页面,就能立马开始体验 React 的魅力了。
我是准备在项目中正式使用,用这种方式就无法应用到各种现代化和流程化的前端工具,比如 Webpack。所以会选择基于 node.js 的方案。
这次除了要尝试 React,另外一个挑战就是不依赖之前 Web 框架「傻瓜化」的前端配置。就像 Laravel 提供的 mix,它会让你不必关心前端要如何配置打包工具,需要些什么组件和扩展。这些基础的工作它都做好了。虽然使用起来非常爽,但时间一长,我发现自己已经快跟不上前端技术各种日新月异的变化,而且也特别依赖这种提供基础配置的框架。这让我有点担心自己逐渐会在项目中会失去对前端技术的掌控。
所以我要从零开始尝试自己搭建一个 React 的开发环境,即便是要添加依赖组件,也需要弄明白为什么需要它。
这样一来,使用 npx create-react-project
创建 React 项目脚手架的命令也就被我放弃了。它虽然相比其他框架提供的前端配置精简了许多,但 package.json
里面依然还是有很多我不太了解的依赖配置。
我的目的很简单,就是要从零开始搭建一个 React 项目环境。说的更具体一点就是要一点一点的实现一个可以编译 React 组件并显示在浏览器上的基础目录,以方便我正式使用时进行扩展和补充。
显示一个页面
万事开头难。我要完成的第一个目标就设置的简单点:规划好目录并显示一个简单的项目页面。先创建项目目录:
mkdir react-app
react-app 是项目目录的名称,这里代表这次实验用的名称。进入项目目录,我还需要创建两个文件夹:
cd react-app
mkdir src
mkdir public
src 目录用来存放项目 js 源码,public 目录用来存放打包好的 js 文件以及一些静态资源。
接下来在 src 目录中创建一个项目源码的入口文件:
touch src/main.js
里面暂时还不需要任何内容。
接下来在 public 目录创建一个 HTML 文件,用来作为浏览器的访问入口:
touch public/index.html
为了方便验证效果,在这个 HTML 文件中添加以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Demo</title>
</head>
<body>
<h1>This a React Demo app.</h1>
</body>
</html>
接下来就需要用到 Node.js 环境了,我已经安装好了,并且可以正常使用 npm
或 yarn
命令。我倾向于使用 yarn
命令,关于原因可以查看我之前写的这篇文章《2021 JavaScript 包管理工具入门指南》。
确保 yarn
命令可用后,用它来初始化一个默认的 js 包配置文件:
yarn init -y
命令执行完后,当前项目目录下会多出一个 package.json
文件。接下来开始添加 Webpack 工具库:
yarn add webpack webpack-cli webpack-dev-server
webpack 是 Webpack 主工具库,webpack-cli 和 webpack-dev-server 是为了给项目提供开发时的 Web 访问服务功能。
安装好 Webpack 相关库后,编辑 package.json
文件,需要在里面添加一行自定义脚本,完整的内容如下:
{
"name": "app",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server"
},
"dependencies": {
"webpack": "^5.64.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.5.0"
}
}
其中 "scripts"
节点就是新添加的自定义脚本内容。后面的 start
代表一个自定义指令,指向了 webpack-dev-server
命令。它会启动一个可供浏览器访问的 Web 服务。
最后再创建一个 Webpack 配置文件:
touch webpack.config.js
并添加以下配置内容:
module.exports = {
mode: 'development',
devServer: {
host: 'localhost',
port: 8000
},
entry: './src/main.js',
output: {
filename: 'bundle.[hash].js'
}
}
其中 devServer
节点定义了浏览器中可以访问的项目地址和端口。来尝试运行一下刚才在 package.json
中自定义的开发服务指令:
yarn start
打开浏览器,访问 http://localhost:8000
,一切正常的话就可以看到以下内容。
成功迈出了第一步。目前项目下的文件结构看起来如下:
.
├── node_modules/
├── package.json
├── public/
│ └── index.html
├── src/
│ └── main.js
├── webpack.config.js
└── yarn.lock
各文件和目录的解释如下:
- node_modules:通过
yarn
命令安装的组件源码目录。 - package.json:项目包和依赖信息文件。
- public:编译打包和静态资源目录。
- src:项目源码目录。
- webpack.config.js:Webpack 配置文件。
- yarn.lock:通过
yarn
命令安装组件后当前的版本锁定信息文件。
显示 React 组件
只显示一个原始的 HTML 页面还没多大用处,所以接下来就是实现最终目的:实现 React 组件的功能显示。
在前面的基础工作上,这一步其实已经不再复杂了。首先是安装 Babel 代码转译工具库:
yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react
接着继续引入 React 的依赖库:
yarn add react react-dom
再添加一个 Webpack 的 HTML 插件,它能辅助处理访问入口页面的脚本插入:
yarn add html-webpack-plugin
这样核心的依赖组件和库就全部到位,接下来就是完善代码和配置的工作。
首先补充一下 Webpack 配置文件。打开 webpack.config.js
,然后修改成如下的内容:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
devServer: {
host: 'localhost',
port: 8000,
hot: true
},
entry: './src/main.js',
output: {
filename: 'bundle.[hash].js'
},
module: {
rules: [
{
test: /\.(js)$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'public/index.html'
})
]
}
主要新增了 module
和 plugins
节点。然后 devServer
节点补充了一个 hot: true
的配置项,这个配置可以实现修改源码后自动刷新浏览器的功能,非常实用。
在 public/index.html
文件中添加一个渲染组件时要绑定的节点元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React Demo</title>
</head>
<body>
<h1>This a React Demo app.</h1>
<div id="app"></div>
</body>
</html>
上面 id="app"
那行就是刚添加的,这是要绑定组件的节点标签。
另外还需要创建一个 Babel 的配置文件,文件名为 .babelrc
,放到项目的根目录,内容如下:
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
最后编辑 src/main.js
文件,写一个简单的 React 组件:
import React from 'react';
import ReactDOM from 'react-dom';
// 一个欢迎消息组件
class Welcome extends React.Component {
render() {
return <h1>Welcome, { this.props.name }.</h1>;
}
}
// 绑定并渲染组件内容到入口页面的 #app 标签元素
ReactDOM.render(<Welcome name="zzxworld" />, document.getElementById('app'))
再次运行 yarn start
命令,然后在浏览器访问 http://localhost:8000
,一切正常的话应该会发现下面多了一行信息。
这说明 React 组件正常显示了。可以在 src/main.js
中把 zzxworld
换成别的名字试试,如果在保存代码的那一刻,浏览器内容自动变了,那说明自动刷新功能也起作用了。
至此,这个最基础的 React 开发环境就算完成了,我也已经迫不及待的想要在实际项目中去体验 React。