都2022年了,手动搭建React开发环境很难吗?

工厂流水线生产的东西用久了,总想着自己手工是否也能做出来,就如同工艺品和艺术品一般,虽然效果相似,但艺术品往往比工艺品更有韵味。

成都创新互联公司是专业的高安网站建设公司,高安接单;提供网站建设、做网站,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行高安网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

作为一名前端工程师,总是用一些脚手架来快速搭建新项目的基本结构,因此今天尝试着一步步搭建一个 React 的项目环境,看看需要处理哪些问题,查漏补缺!

一、需求分析 

首先分析我们的诉求:

  • 应用级别的项目,是需要支持打包构建。
  • 需要考虑兼容性,支持代码 pollyfill。
  • 支持 React 框架下的开发环境。
  • 支持代码类型提示。
  • 支持前端路由。
  • 支持前端状态管理。
  • 代码规范、自动格式化、Git 提交规范。
  • 基础的 UI 组件库。

针对上面的诉求,其实也是绝大部分项目都会需要,因此也有了常见的解决方案:

  • Webpack 5。
  • Babel。
  • React 17、React-dom。
  • TypeScript。
  • React-router-dom v6。
  • Redux、React-redux。
  • ESlint、Prettier、Lint-staged、Husky、@commitlint。
  • Arco Design。

二、项目打包构建

因为是 2022 年了,所以我们的项目所有依赖项全部用最新的工具库版本,搞起来!

首先是把项目的基本构建能力搭建好,让项目先跑起来!

1、 初始化 package.json

mkdir webpack-react
cd webpack-react
npm init --y
git init

然后稍微改改 package.json 文件如下:

{
"name": "webpack-react",
"private": true,
"version": "0.1.0",
"description": "一个基于 Webpack 构建的 React开发环境",
"main": "index.js",
"scripts": {
"dev": "",
"build": "",
"preinstall": "npx only-allow yarn"
},
"keywords": [],
"author": "DYBOY",
"license": "ISC"
}

由于没有安装一些三方库,所以该文件还比较“简陋”,所以接下来逐个安装模块,配置环境!

2、安装配置 React 和 Typescript

根据需求,我们先安装一些必要的模块。

首先是 React 的基本模块。

yarn add react react-dom
yarn add @types/react @types/react-dom

然后是 TypeScript 类型模块。

yarn add typescript -D

有了 TypeScript,就可以直接通过 TS 生成一个 tsconfig.json 的配置文件

yarn tsc --init

根据需要,稍微改改后如下:

// tsconfig.json
{
"compilerOptions": {
"target": "ES2015",
"lib": ["DOM", "ES2015"],
"jsx": "react-jsx",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"module": "ESNext",
"rootDir": "./src",
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"resolveJsonModule": true,
"allowJs": true,
"outDir": "./dist",
"removeComments": true,
"isolatedModules": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src/"]
}

*关于 tsconfig.json 文件的配置解析可以参阅:《会写 TypeScript 但你真的会 TS 编译配置吗?[1]》。

此时可以创建文件和文件夹,有一个初步的项目结构。

项目结构

其中:

  • dist/:是用于存储打包的文件。
  • public/:是用于存放打包的模板入口 HTML 文件。
  • src/:是用于开发人员主要编码的文件夹。
  • .gitignore:用于配置 Git 忽略哪些文件或文件夹。
  • tsconfig.json:TypeScript 的项目配置文件。
  • yarn.lock:依赖模块的版本信息,用于保证开发环境一致性。

此时就可以简单的写支持 TS 和 React 的应用了。

3、 Webpack 相关

因为是一个项目,我们需要通过构建工具,帮助我们快速的实现打包,以及开发环境下的预览,因此第二步就是安装和配置 Webpack。

yarn add webpack webpack-cli webpack-dev-server webpack-merge -D

后两个模块分别是用于开启开发时的本地 HTTP 服务,和用于 Merge webpack 配置的工具函数。

(1) Webpack 配置文件结构

首先,先完善 package.json 中的 scripts(开发指令和构建指令):

+ "dev": "cross-env NODE_ENV=development webpack serve -c scripts/webpack.dev.js",
+ "build": "yarn ts:checker && cross-env NODE_ENV=production webpack -c scripts/webpack.prod.js",
+ "ts:checker": "tsc --noEmit",

同时安装一下 cross-env,该模块主要是用于支持在不同的操作系统下保证环境变量正确。

yarn add cross-env -D

通过指令,我们需要三个 Webpack 的配置文件:

(2) webpack.common.js 通用配置

这是公共的 Webpack 配置,主要配置了如下几个地方。

const path = require("path");
const chalk = require("chalk");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
const pkgJSON = require("../package.json");
console.log("process.env.NODE_ENV: ", process.env.NODE_ENV);
module.exports = {
entry: path.resolve(__dirname, "../src/index.tsx",
output: {
filename: "[name].[hash:8].js",
path: path.resolve(__dirname, "../dist"),
publicPath: "/",
clean: true,
},
resolve: {
extensions: [".ts", ".tsx", ".js"],
alias: {
"@": path.resolve(__dirname, "../src"),
},
},
module: {
rules: [
{
test: /\.tsx?$/,
use: ["ts-loader"],
exclude: /node_modules/,
},
{
test: /\.(jpe?g|png|svg|gif)$/i,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 25 * 1024, // 25kb
},
},
generator: {
filename: "assets/imgs/[name].[hash:8][ext]",
},
},
],
},
plugins: [
new webpack.DefinePlugin({
// 定义在代码中可以替换的一些常量
__DEV__: process.env.NODE_ENV === "development",
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "../public/index.html"),
title: pkgJSON.name,
meta: {
description: {
type: "description",
content: pkgJSON.description,
},
},
minify: "auto",
}),
new ProgressBarPlugin({
format: ` :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,
}),
],
};

个人有一个观点,开发环境和构建环境应该在配置上相似性需要寻找平衡,开发环境寻求的是热更新快,构建环境寻求的是兼容性好,且尽可能和开发环境看到效果相同!

针对缺失的模块还需要安装到开发依赖中:

# 支持 ts 和 tsx 文件的处理
yarn add ts-loader -D
# 美化终端输出,安装特定版本是为了处理模块化包的问题
yarn add chalk@4.1.2 -D
# 将 /public/index.html 作为模板入口文件打包
yarn add html-webpack-plugin -D
# 美化 webpack 编译时候的进度条
yarn add progress-bar-webpack-plugin -D

(3) webpack.dev.js 开发配置

然后再配置下开发环境下的 Webpack 配置,主要是支持热更新、本地预览功能,以及一些和生产环境差异的配置。

const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development", // 开发模式
devServer: {
hot: true, // 热更新
open: true, // 编译完自动打开浏览器
compress: false, // 关闭gzip压缩
port: 7878, // 开启端口号
historyApiFallback: true, // 支持 history 路由重定向到 index.html 文件
},
module: {
// 插件的执行顺序从右到左
rules: [
{
test: /\.(css|scss|sass)$/,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [["autoprefixer"]],
},
},
},
"sass-loader",
],
// 排除 node_modules 目录
exclude: /node_modules/,
},
],
},
stats: "errors-only", // Webpack 在编译的时候只输出错误日志,终端更清爽
});

这里增加了对 scss/css 文件的处理,因此还需要安装相关的模块:

# style-loader 将 css 注入到 HTML 的内联样式
# css-loader 用于加载 CSS 文件,转化 CSS 为 CommonJS
yarn add style-loader css-loader -D
# postcss 用于处理 CSS 兼容性
# autoprefixer 用于自动根据兼容需求增加 CSS 属性的前缀
yarn add postcss postcss-loader autoprefixer -D
# sass 主要是用于支持 “CSS 编程”
# sass-loader 会将 .scss 后缀文件编译成 CSS
yarn add sass sass-loader -D

讲到了 CSS 自动前缀处理兼容性,因此可以将需要兼容浏览器版本的配置放到 package.json -> browserslist 属性下:

{
...
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 9",
"last 3 iOS versions"
]
}
...
}

(4) webpack.prod.js 生产配置

针对 Webpack 的构建环境下(mode: "production")的配置,实际上在 Webpack 5 版本中默认就集成了很多优化,更多自定义诉求可以参考:Webpack Optimization[2] 配置。

const { merge } = require("webpack-merge");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "production",
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
terserOptions: {
format: {
comments: false,
},
},
extractComments: false,
}),
],
},
module: {
rules: [
{
test: /\.(css|scss|sass)$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [["autoprefixer"]],
},
},
},
"sass-loader",
],
exclude: /node_modules/,
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "assets/css/[hash:8].css",
}),
],
});

需要安装依赖:

# 用于将 CSS 导出到单独文件
yarn add mini-css-extract-plugin -D
# 用于做源代码压缩
yarn add terser-webpack-plugin -D

(5) 开发&构建

弄好了上面的 Webpack 配置,就可以实际的开发了。

/src/index.tsx 文件如下:

执行:yarn dev,会自动打开浏览器页面:http://localhost:7878/。

执行:yarn build,会将项目编译打包输出到 ./dist/ 文件夹下。

4、 Bable 处理兼容性

我们的项目可能会在各种浏览器中运行,为了尽可能兼容大多数用户的设备,因此引入 Babel 来统一处理兼容性。

在 webpack.common.js 配置文件中增加:

...
rules: [
{
test: /\.tsx?$/,
use: [
+ {
+ loader: "babel-loader",
+ options: {
+ presets: [
+ [
+ "@babel/preset-env", // 预制配置
+ {
+ corejs: {
+ version: 3,
+ },
+ useBuiltIns: "usage", // 按需引入 pollyfill
+ },
+ ],
+ "@babel/preset-react", // React 环境
+ ],
+ plugins: ["@babel/plugin-transform-runtime"],
+ },
+ },
"ts-loader",
],
exclude: /node_modules/,
},
...
],
...

放到 webpack.common.js 文件下也是为了考虑在开发环境下验证引入 pollyfill 的正确性。

同时还需要安装如下依赖:

# 安装 babel 核心和加载器
yarn add @babel/core babel-loader -D
# core-js 中有各种各样的 pollyfill,用于提升兼容性
# https://github.com/zloirock/core-js
yarn add core-js -D
# 预制环境
yarn add @babel/preset-env @babel/preset-react -D
# 统一的 pollyfill,打包时候加载到代码中,减少冗余代码
yarn add @babel/plugin-transform-runtime -D

三、路由 React-router-dom

前端的页面一般是多页面的,因此我们需要一个统一的路由来方便管理,这里用到了 react-router-dom v6[3] 版本。

多路由的使用方式基本相似,因此官方提炼出了 useRoutes 的 Hooks,用于便捷生成路由,相较于 V5 版本,确实方便太多了。

安装作为应用依赖:

yarn add react-router-dom

1、 统一管理的路由配置首先是配置

路由 /src/config/router.tsx 文件:

import { RouteObject } from "react-router-dom";
import HomePage from "@/pages/home";
const ROUTER_CONFIG: RouteObject[] = [
{
path: "/",
element: ,
},
{
path: "*",
element: <>404 Not Found!,
},
];
export { ROUTER_CONFIG };

之后如果新增任意页面,都可以在 /src/pages/ 文件夹下新增任,并且都可以放到 /src/config/router.tsx 文件来统一管理,嵌套路由同样适用,只需要根据 RouteObject 类型声明规范即可:

/**
* A route object represents a logical route, with (optionally) its child
* routes organized in a tree-like structure.
*/
export interface RouteObject {
caseSensitive?: boolean; // 大小写敏感
children?: RouteObject[]; // 子路由
element?: React.ReactNode; // 组件
index?: boolean; // 在子路由中,默认为父级路由的首页
path?: string; // URL 路径
}

2、 项目中引入

然后在 /src/app.tsx 文件中使用 useRoutes() 并嵌入到应用中:

import { useRoutes } from "react-router-dom";
import { ROUTER_CONFIG } from "./config/router";
const App = () => {
const appRoutesElement = useRoutes(ROUTER_CONFIG);
return appRoutesElement;
};

export default App;

最后在 /src/inde.tsx 使用 BrowserRouter 包裹 组件。

import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./app";

render(


,
document.getElementById("root")
);

此时的项目目录结构如下:

目录结构

如此就可以愉快的编写任意页面啦!

3、 [优化]延迟按需加载页面

虽然路由集中管理了,但是首屏加载的 js 文件太大,会使得白屏时间较长,增加了用户等待时间。

因此考虑延迟按需加载页面方式,使用 import() 和 React.lazy() 来主动优化。

新建一个通用组件 LazyWrapper 在 /src/components/lazy-wrapper/index.tsx 文件。

import { FC, lazy, Suspense } from "react";
interface LazyWrapperProps {
/** 组件路径: 在 src/pages 目录下的页面路径,eg: /home => src/pages/home/index.tsx */
path: string;
}
/**
* 懒加载组件包装器
*/
const LazyWrapper: FC = ({ path }) => {
const LazyComponent = lazy(() => import(`/src/pages${path}`));

return (
loading... 分享文章:都2022年了,手动搭建React开发环境很难吗?
本文来源:http://www.gawzjz.com/qtweb2/news42/10792.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联