目录
5.6 添加 npm 脚本, 用于自动修复部分语法不规范的代码
7.2 配置 commitlint 和 commitizen
8.6 raw-loader 用于加载文本内容(.txt、.md 文件)
一、 初始化项目
- 创建项目目录
- 初始化 npm 项目
npm init -y
复制代码
- 初始化 git 项目
# 初始化项目
git init
# 添加 .gitignore
echo "/node_modules\n/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 安装基础插件包
- 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
复制代码
- 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
- 添加对 css 样式文件的支持
- 添加对 scss 样式文件的支持
- 使用 mini-css-extract-plugin 将 mini-css-extract-plugin
- 添加 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 代码测试
- 创建
src/index.css
.css {
padding-top: 20px;
}
复制代码
- 创建
src/index.module.css
.module-css {
padding-right: 20px;
}
复制代码
- 创建
src/index.scss
.scss {
padding-bottom: 20px;
}
复制代码
- 创建
src/index.module.scss
.module-scss {
padding-left: 20px;
}
复制代码
- 修改
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'));
复制代码
- 运行项目测试样式是否正确加载
四、 添加对图片的支持
这里其实没什么好讲的, 主要使用
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
脚本说明:
- release: 自定义要发布的版本, 如:
npm run release -- 1.0.0
- release:100: 执行该脚本, 那么如果当前版本是 1.0.0 那么版本将被提升至 2.0.0
- release:010: 执行该脚本, 那么如果当前版本是 1.0.0 那么版本将被提升至 1.1.0
- release:001: 执行该脚本, 那么如果当前版本是 1.0.0 那么版本将被提升至 1.0.1
{
"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',
+ },
]
}
};