目录
一、 初始化项目
二、 Webpack 配置
2.1 基础配置设置
2.2 安装基础插件包
2.3 测试
2.4 总结
三、 添加对 scss 样式文件的支持
3.1 TODO
3.2 webpack 配置修改
3.3 安装依赖
3.4 代码测试
四、 添加对图片的支持
4.1 webpack 修改
4.2 依赖安装
4.3 测试
五、 esling 配置
5.1 webpack 配置修改
5.2 项目下添加 .eslintrc.js 配置文件
5.3 项目下添加 .eslintignore
5.4 安装依赖
5.5 测试
5.6 添加 npm 脚本, 用于自动修复部分语法不规范的代码
六、 引入 Antd 并配置按需加载
6.1 修改 .babelrc
6.2 依赖安装
6,3 测试
七、 版本发布、git commit 规范校验配置
7.1 依赖包安装
7.2 配置 commitlint 和 commitizen
7.3 更新 package.json
7.4 commit 方式
7.5 版本发布流程
八、 更多配置
8.1 webpack 拷贝 public 文件
8.2 定义全局变量
8.3 自动加载依赖
8.4 webpack 定义路径别名
8.5 cross-env 设置环境变量
8.6 raw-loader 用于加载文本内容(.txt、.md 文件)
npm init -y
复制代码
# 初始化项目
git init
# 添加 .gitignore
echo "/node_modules\n/build" >> .gitignore
# 关联远程仓库
git remote add origin
复制代码
/src/index.js
作为 webpack 的入口文件import React from 'react';
import reactDom from 'react-dom';
const App = () => (
test page
);
reactDom.render( , document.getElementById('root'));
复制代码
/public/index.html
webpack 打包后的文件将添加到该文件
Document
复制代码
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"
}
复制代码
npm i webpack webpack-cli html-webpack-plugin webpack-dev-server babel-loader @babel/core @babel/preset-react @babel/preset-env -D
复制代码
npm i react react-dom
复制代码
npm start
测试项目是否能够正常运行npm run build
测试是否能够正常对项目进行打包、编译, 编译后目录结构如下.
├── index.html
└── js
└── main.0b16f9b82b7fb2c9ba47.bundle.js
复制代码
到这里一个最基本的 React 项目就已经搭建起来了, 但如果只是这些配置简单配置肯定是远远不够的, 上面只是为了说明其实要搭建一个 React 基础项目还是很简单的, 剩下的工作就是不断的根据具体需求扩充项目配置。下面开始会简单根据需要对项目的配置进行扩展, 比如:
.module.css
.module.scss
的样式文件启用模块化+ 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,
],
};
复制代码
npm i mini-css-extract-plugin css-loader sass-loader node-sass -D
复制代码
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 = () => (
+
test page
);
reactDom.render( , document.getElementById('root'));
复制代码
这里其实没什么好讲的, 主要使用
url-loader
对图片进行处理, 需要特别注意的是该插件依赖于file-loader
module.exports = {
module: {
rules: [
+ {
+ test: /\.(png|jpg|gif|woff|svg|eot|ttf)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: 'assets/[hash].[ext]',
+ },
+ }],
+ },
],
},
};
复制代码
npm i url-loader file-loader -D
复制代码
没什么好说的, 找一张图片在 src/index.js
中引用看是否能够正常显示即可
import React from 'react';
import reactDom from 'react-dom';
import Img from './1519971416-JDHjSqWCph.jpg';
const App = () => (
);
reactDom.render( , document.getElementById('root'));
复制代码
这里只需在 babel-loader
之后添加 eslint-loader
, 需要特别注意的是它们的顺序
module.exports = {
module: {
rules: [
{
test: /\.(mjs|js|jsx)$/,
exclude: /node_modules/,
+ use: ['babel-loader', 'eslint-loader'],
},
],
},
};
复制代码
.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"],
}
}
复制代码
.eslintignore
# 设置需要忽略的文件
/src/assets/*
复制代码
npm i eslint babel-eslint eslint-loader eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks -D
复制代码
修改 src/index.js
import React from 'react';
import reactDom from 'react-dom';
const App = () => (
test page
)
reactDom.render( , document.getElementById('root'));
复制代码
重新运行项目, 如果配置正常则会抛出警告
"scripts": {
+ "eslint:fix": "eslint --fix ./src"
},
复制代码
通过执行 npm run eslint:fix
则会修复项目中部分能够自动修复的不规范代码
这里主要为 .babelrc
配置添加插件 babel-plugin-import
从而实现 antd 的按需加载
.babelrc
说明: 配置插件时可以设置实例化名称 import-antd
, 这样就可以多次使用同一插件, 如果你还需要使用 babel-plugin-import
处理其他组件库
{
+ "plugins": [
+ ["import", {
+ "libraryName": "antd",
+ "libraryDirectory": "es",
+ "style": "css"
+ }, "import-antd"]
+ ],
"presets": [
"@babel/preset-react",
"@babel/preset-env"
]
}
复制代码
npm i antd
npm i babel-plugin-import -D
复制代码
在 src/index
中引用样式, 测试是否能够正常使用
import React from 'react';
import reactDom from 'react-dom';
+ import { Button } from 'antd';
const App = () => (
+
);
reactDom.render( , document.getElementById('root'));
复制代码
这一节节选我另一篇文章 commit 规范校验配置和版本发布配置
, 下面只介绍简单配置方法
# 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
复制代码
# 生成 commitlint 配置文件
echo "module.exports = {extends: ['@commitlint/config-angular']};" > commitlint.config.js
# commitizen 初始化
commitizen init cz-conventional-changelog --save-dev --save-exact
复制代码
脚本说明:
- 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"
+ }
+ }
}
复制代码
git cz
或者 npm run commit
来提交代码npm run commit
来提交代码# 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
复制代码
+ const CopyWebpackPlugin = require('copy-webpack-plugin');
+ const copyWebpackPlugin = new CopyWebpackPlugin(
+ [{ from: path.resolve(__dirname, '../public') }]
+ );
module.exports = {
plugins: [
+ copyWebpackPlugin,
]
};
复制代码
+ 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,
]
};
复制代码
+ const { ProvidePlugin } = require('webpack');
+ const providePlugin = new ProvidePlugin({
+ _: 'lodash',
+ lodash: 'lodash',
+ });
module.exports = {
plugins: [
+ providePlugin,
]
};
复制代码
module.exports = {
resolve: {
+ alias: config.alias || {},
},
};
复制代码
优点: 兼容多个平台
{
"scripts": {
+ "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
}
}
复制代码
module.exports = {
module: {
rules: [
+ {
+ test: /\.(text|md)$/,
+ use: 'raw-loader',
+ },
]
}
};