综合开发

纯手动搭建 React 项目

微信扫一扫,分享到朋友圈

纯手动搭建 React 项目
  • 创建项目目录
  • 初始化 npm 项目
npm init -y
复制代码
  • 初始化 git 项目
# 初始化项目
git init
# 添加 .gitignore
echo "/node_modulesn/build" >> .gitignore
# 关联远程仓库
git remote add origin <url>
复制代码

二、 Webpack 配置

2.1 基础配置设置

  • 创建文件 /src/index.js
    作为 webpack 的入口文件
import React from 'react';
import reactDom from 'react-dom';
const App = () => (
<div>
test page
</div>
);
reactDom.render(<App/>, document.getElementById('root'));
复制代码
  • 创建模板文件 /public/index.html
    webpack 打包后的文件将添加到该文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
复制代码
  • 创建 webpack
    开发环境下配置文件 /webpack/webpack.config.dev.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const htmlWebpackPlugin = new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
});
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/index.js'),
output: {
path: path.resolve(__dirname, '../build'),
filename: 'js/[name].[hash].bundle.js',
},
module: {
rules: [
{
test: /.(mjs|js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
}
],
},
plugins: [
htmlWebpackPlugin,
],
resolve: {
extensions: ['.mjs', '.js', '.jsx'],
},
};
复制代码
  • 创建 webpack
    生产环境下配置文件 /webpack/webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const htmlWebpackPlugin = new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
});
module.exports = {
mode: 'production',  // 和开发环境下的配置只是修改了 mode
entry: path.resolve(__dirname, '../src/index.js'),
output: {
path: path.resolve(__dirname, '../build'),
filename: 'js/[name].[hash].bundle.js',
},
module: {
rules: [
{
test: /.(mjs|js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
}
],
},
plugins: [
htmlWebpackPlugin,
],
resolve: {
extensions: ['.mjs', '.js', '.jsx'],
},
};
复制代码
  • 创建 babel
    配置文件 .babelrc
{
"presets": [
"@babel/preset-react",
"@babel/preset-env"
]
}
复制代码
  • 修改 package.json
    : 添加 npm 脚本
"scripts": {
+  "start": "webpack-dev-server --config ./webpack/webpack.config.dev.js --open",
+  "build": "rm -rf build/* && webpack --config ./webpack/webpack.config.js"
}
复制代码

2.2 安装基础插件包

  1. webpack 相关依赖包、插件
  • webpack: webpack 基础包
  • webpack-cli: webpack cli 工具包
  • html-webpack-plugin: webpack 插件, 用于将打包后的文件添加到指定的 html 内
  • webpack-dev-server: webpack 开发环境工具, 创建一个开发环境
  • babel-loader: weboack loader, 用于编译打包 js 文件
  • @babel/core: babel 依赖包, 将 js 代码分析成 ast
  • @babel/preset-react: webpack react 相关预设
  • @babel/preset-env: weboack react 相关预设, 这样就可以使用最新的 js 相关语法
npm i webpack webpack-cli html-webpack-plugin webpack-dev-server babel-loader @babel/core @babel/preset-react @babel/preset-env -D
复制代码
  1. react 相关依赖包、包
  • react
  • react-dom
npm i react react-dom
复制代码

2.3 测试

npm start
npm run build
.
├── index.html
└── js
└── main.0b16f9b82b7fb2c9ba47.bundle.js
复制代码

2.4 总结

到这里一个最基本的 React 项目就已经搭建起来了, 但如果只是这些配置简单配置肯定是远远不够的, 上面只是为了说明其实要搭建一个 React 基础项目还是很简单的, 剩下的工作就是不断的根据具体需求扩充项目配置。下面开始会简单根据需要对项目的配置进行扩展, 比如:

  • webpack 添加对 scss 样式文件的解析
  • webpack 添加对图片的解析
  • 项目添加 eslint 配置
  • 项目添加版本发布、git commit 规范配置
  • 项目添加对 antd 的支持, 并配置按需加载模块

三、 添加对 scss 样式文件的支持

3.1 TODO

  1. 添加对 css 样式文件的支持
  2. 添加对 scss 样式文件的支持
  3. 使用 mini-css-extract-plugin 将 mini-css-extract-plugin
  4. 添加 css 模块化的支持, 对 .module.css
    .module.scss
    的样式文件启用模块化

3.2 webpack 配置修改

+ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+ const miniCssExtractPlugin = new MiniCssExtractPlugin({
+   filename: 'style/[name].[hash].css',
+   chunkFilename: 'style/[id].[hash].css',
+ });
+ const cssRegex = /.(css|scss)$/;
+ const cssModuleRegex = /.module.(css|scss)$/;
module.exports = {
module: {
rules: [
+     {
+       test: cssRegex,
+       exclude: cssModuleRegex,
+       sideEffects: true,
+       use: [
+         {
+           loader: MiniCssExtractPlugin.loader,
+           options: {
+             hmr: process.env.NODE_ENV === 'development',
+           },
+         },
+         { loader: 'css-loader', options: { importLoaders: 1 } },
+         'sass-loader',
+       ],
+     },
+     {
+       test: cssModuleRegex,
+       use: [
+         {
+           loader: MiniCssExtractPlugin.loader,
+           options: {
+             hmr: process.env.NODE_ENV === 'development',
+           },
+         },
+         {
+           loader: 'css-loader',
+           options: {
+             modules: {
+               localIdentName: '[local]__[hash:base64]',
+             },
+           },
+         },
+         'sass-loader',
+       ],
+     }
],
},
plugins: [
+   miniCssExtractPlugin,
],
};
复制代码

3.3 安装依赖

  • css-loader
  • sass-loader
  • node-sass: scss
  • mini-css-extract-plugin
npm i mini-css-extract-plugin css-loader sass-loader node-sass -D
复制代码

3.4 代码测试

  1. 创建 src/index.css
.css {
padding-top: 20px;
}
复制代码
  1. 创建 src/index.module.css
.module-css {
padding-right: 20px;
}
复制代码
  1. 创建 src/index.scss
.scss {
padding-bottom: 20px;
}
复制代码
  1. 创建 src/index.module.scss
.module-scss {
padding-left: 20px;
}
复制代码
  1. 修改 src/index.js
import React from 'react';
import reactDom from 'react-dom';
+ import css from './index.module.css';
+ import scss from './index.module.scss';
+ import './index.css';
+ import './index.scss';
const App = () => (
+ <div className={`
+   css
+   scss
+   ${css['module-css']}
+   ${scss['module-scss']}
+ `}>
test page
</div>
);
reactDom.render(<App/>, document.getElementById('root'));
复制代码
  1. 运行项目测试样式是否正确加载

四、 添加对图片的支持

这里其实没什么好讲的, 主要使用 url-loader
对图片进行处理, 需要特别注意的是该插件依赖于 file-loader

4.1 webpack 修改

module.exports = {
module: {
rules: [
+     {
+       test: /.(png|jpg|gif|woff|svg|eot|ttf)$/,
+       use: [{
+         loader: 'url-loader',
+         options: {
+           limit: 10000,
+           name: 'assets/[hash].[ext]',
+         },
+       }],
+     },
],
},
};
复制代码

4.2 依赖安装

npm i url-loader file-loader -D
复制代码

4.3 测试

没什么好说的, 找一张图片在 src/index.js
中引用看是否能够正常显示即可

import React from 'react';
import reactDom from 'react-dom';
import Img from './1519971416-JDHjSqWCph.jpg';
const App = () => (
<div>
<img src={Img} />
</div>
);
reactDom.render(<App/>, document.getElementById('root'));
复制代码

五、 esling 配置

5.1 webpack 配置修改

这里只需在 babel-loader
之后添加 eslint-loader
, 需要特别注意的是它们的顺序

module.exports = {
module: {
rules: [
{
test: /.(mjs|js|jsx)$/,
exclude: /node_modules/,
+       use: ['babel-loader', 'eslint-loader'],
},
],
},
};
复制代码

5.2 项目下添加 .eslintrc.js
配置文件

module.exports = {
parser: 'babel-eslint',
// 开发环境设置: 在使用下拉环境中的全局变量时不会因为未定义变量而报错, 如 window
env: {
browser: true,
node: true
},
// 定义全局变量, 在直接使用下列全局变量情况下不会因为未定义变量而报错
globals: {
_: true,
lodash: true,
},
// 插件列表
plugins: [
'react',
'import',
'react-hooks',
],
// 继承的规则
extends: [
'eslint:recommended',
'plugin:react/recommended',
],
// 自定义规则列表
rules: {
// 强制在每个语句后面使用分号
"semi": [1, "always"],
}
}
复制代码

5.3 项目下添加 .eslintignore

# 设置需要忽略的文件
/src/assets/*
复制代码

5.4 安装依赖

  • eslint
  • babel-eslint
  • eslint-loader
  • eslint-plugin-import
  • eslint-plugin-react
  • eslint-plugin-react-hooks
npm i eslint babel-eslint eslint-loader eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks -D
复制代码

5.5 测试

修改 src/index.js

import React from 'react';
import reactDom from 'react-dom';
const App = () => (
<div>
test page
</div>
)
reactDom.render(<App/>, document.getElementById('root'));
复制代码

重新运行项目, 如果配置正常则会抛出警告

5.6 添加 npm 脚本, 用于自动修复部分语法不规范的代码

"scripts": {
+   "eslint:fix": "eslint --fix ./src"
},
复制代码

通过执行 npm run eslint:fix
则会修复项目中部分能够自动修复的不规范代码

六、 引入 Antd 并配置按需加载

这里主要为 .babelrc
配置添加插件 babel-plugin-import
从而实现 antd 的按需加载

6.1 修改 .babelrc

说明: 配置插件时可以设置实例化名称 import-antd
, 这样就可以多次使用同一插件, 如果你还需要使用 babel-plugin-import
处理其他组件库

{
+ "plugins": [
+   ["import", {
+     "libraryName": "antd",
+     "libraryDirectory": "es",
+     "style": "css"
+   }, "import-antd"]
+ ],
"presets": [
"@babel/preset-react",
"@babel/preset-env"
]
}
复制代码

6.2 依赖安装

npm i antd
npm i babel-plugin-import -D
复制代码

6,3 测试

src/index
中引用样式, 测试是否能够正常使用

import React from 'react';
import reactDom from 'react-dom';
+ import { Button } from 'antd';
const App = () => (
<div>
+   <Button type="primary">按钮</Button>
</div>
);
reactDom.render(<App/>, document.getElementById('root'));
复制代码

七、 版本发布、git commit 规范校验配置

这一节节选我另一篇文章 commit 规范校验配置和版本发布配置
, 下面只介绍简单配置方法

7.1 依赖包安装

# husky 包安装
npm install husky --save-dev
# commitlint 所需包安装
npm install @commitlint/config-angular @commitlint/cli --save-dev
# commitizen 包安装
npm install commitizen --save-dev
npm install commitizen -g
# standard-version 包安装
npm install standard-version --save-dev
复制代码

7.2 配置 commitlint 和 commitizen

# 生成 commitlint 配置文件
echo "module.exports = {extends: ['@commitlint/config-angular']};" > commitlint.config.js
# commitizen 初始化
commitizen init cz-conventional-changelog --save-dev --save-exact
复制代码

7.3 更新 package.json

脚本说明:

npm run release -- 1.0.0
{
"scripts": {
+   "commit": "git-cz",
+   "release": "standard-version --release-as",
+   "release:100": "npm run release -- major",
+   "release:010": "npm run release -- minor",
+   "release:001": "npm run release -- patch",
},
+ "husky": {
+   "hooks": {
+     "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
+   }
+ }
}
复制代码

7.4 commit 方式

  • 全局安装 commitizen 情况下可使用 git cz
    或者 npm run commit
    来提交代码
  • 未全局安装 commitizen 情况下可使用 npm run commit
    来提交代码

7.5 版本发布流程

# 1. 切换到指定分支
git checkout master
# 2. 更新代码
git pull origin master
# 3. 版本发布: 生成 CHANGELOG.md 并创建 tag
npm run release -- --release-as 1.0.0
# 4. 更新 tag 至远程分支
git push --follow-tags origin master
复制代码

八、 更多配置

8.1 webpack 拷贝 public 文件

+ const CopyWebpackPlugin = require('copy-webpack-plugin');
+ const copyWebpackPlugin = new CopyWebpackPlugin(
+   [{ from: path.resolve(__dirname, '../public') }]
+ );
module.exports = {
plugins: [
+   copyWebpackPlugin,
]
};
复制代码

8.2 定义全局变量

+ const { DefinePlugin } = require('webpack');
+ const definePlugin = new DefinePlugin({
+   _DEV_: false,
+   GLOBAL_SERVICE: {
+     HOST: JSON.stringify('https://www.qianyin925.com:4000'),
+     GRAPHQL_URL: JSON.stringify('/graphql'),
+   },
+ });
module.exports = {
plugins: [
+   definePlugin,
]
};
复制代码

8.3 自动加载依赖

+ const { ProvidePlugin } = require('webpack');
+ const providePlugin = new ProvidePlugin({
+   _: 'lodash',
+   lodash: 'lodash',
+ });
module.exports = {
plugins: [
+   providePlugin,
]
};
复制代码

8.4 webpack 定义路径别名

module.exports = {
resolve: {
+   alias: config.alias || {},
},
};
复制代码

8.5 cross-env 设置环境变量

优点: 兼容多个平台

{
"scripts": {
+   "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}
}
复制代码

8.6 raw-loader 用于加载文本内容(.txt、.md 文件)

module.exports = {
module: {
rules: [
{
test: /.(text|md)$/,
use: 'raw-loader',
},
]
}
};
复制代码

Java Math converts to integer

上一篇

了解发布订阅模式之后,vue响应式原理竟如此简单!

下一篇

你也可能喜欢

评论已经被关闭。

插入图片

热门栏目

纯手动搭建 React 项目

长按储存图像,分享给朋友