手动搭建 React 项目

目录

一、 初始化项目

二、 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 项目
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 安装基础插件包

  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 测试

  1. 执行 npm start 测试项目是否能够正常运行
  2. 执行 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

脚本说明:

  1. release: 自定义要发布的版本, 如: npm run release -- 1.0.0
  2. release:100: 执行该脚本, 那么如果当前版本是 1.0.0 那么版本将被提升至 2.0.0
  3. release:010: 执行该脚本, 那么如果当前版本是 1.0.0 那么版本将被提升至 1.1.0
  4. 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',
+     },
    ]
  }
};
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值