目录
第三步:配置TypeScript(非必需,使用可以使项目利于维护和阅读)
前提:已安装Node
第一步:初始化项目
npm init
第二步:安装相关依赖
Babel相关:
基础包,其中 Babel 的核心功能都在 babel/core 模块中。代码转换功能以插件的形式存在,配置 preset-env 插件将支持所有最新的 JavaScript 特性。
babel-loader 是 webpack 用来调用 Babel API 的核心包。
polyfill 模块用于模拟完整的 ES2015+ 环境,它会被添加到全局范围。
npm install --save-dev @babel/core @babel/preset-env babel-loader
npm install --save @babel/polyfill
转换JSX语法
npm install --save-dev @babel/preset-react
类型注释相关(TypeScript)
npm install --save-dev @babel/preset-typescript
模块解析插件(配置导入路径),配置后在导入模块时优化导入路径,可以不指定 ../../ 这种相对路径,默认以项目根目录为搜索路径。
npm install --save-dev babel-plugin-module-resolver
编译类(class)
npm install --save-dev @babel/plugin-proposal-class-properties
编译装饰器(decorator)
npm install --save-dev @babel/plugin-proposal-decorators
按需加载 ,在 antd 等库时按需加载可以优化网络性能
npm install --save-dev babel-plugin-import
配置 Babel:创建 .babelrc 文件,文件内容如下
{
"presets": [
["@babel/preset-env"],
["@babel/preset-react"],
["@babel/preset-typescript"]
],
"plugins": [
["module-resolver",{
"root":["./"]
}],
["@babel/plugin-proposal-decorators",{
"legacy": true
}],
["@babel/plugin-proposal-class-properties",{
"loose": true
}],
["import",{
"libraryName": "antd",
"libraryDirectory": "es",
"style": true
}]
]
}
注意配置文件中 presets 和 plugins 中的配置顺序,presets 中执行顺序是颠倒的,是从后往前执行,preset-typescript 、preset-react 、 preset-env;插件(plugins)运行时是在 presets 之前运行的,插件执行顺序是从前往后。
typeScript相关
安装
npm install --save-dev typescript
npm install --save @types/react @types/react-dom
esLint相关
安装
npm install --save-dev eslint
安装 webpack 中的相应的插件 eslint-loader
npm install --save-dev eslint-loader
初始化,执行后会在根目录下自动创建配置文件 .eslintrc
eslint --init
.eslintrc文件基本配置:
root 表示 ESLint 查找配置时以当前目录为根目录,不再向上查找 .eslintrc 配置。因为 ESLink 是使用层叠配置的形式,它会使用从当前目录找到的配置和一直向上的父文件的配置结合覆盖生成的最终配置,距离文件本身越近的配置文件优先级越高。
extends 表示继承规则。
{ "env": { "es6": true } } 自动启用 es6 语法,"browser" 表示定义浏览器环境中的全局变量,"commonjs" 表示定义CommonJS 全局变量和 CommonJS 作用域 (用于 Browserify/WebPack 打包的只在浏览器中运行的代码)。
ecmaVersion 参数指定使用的 ECMAScript 版本。
globals 配置属性对象表示定义多个项目内的全局变量。
rules 配置属性对象表示定义多个规则配置。如果配置定义在插件中的一个规则时,需使用 插件名/规则ID 的形式。
...
"root": true,
"extends":[ "eslint:recommended" ],
"env": {
"es6": true,
"browser": true,
"commonjs": true
},
"parserOptions":{
"ecmaVersion": 6,
"sourceType": "module",
},
"globals": {
"test": true
},
"rules":{
"no-console": 1,
"plugin1/rule1": "error",
}
...
支持 React ,安装后在 .eslintrc 文件中需修改相关配置(在执行上一步初始化配置文件时步骤里会提示安装,这里可以不用特意安装)。
npm install --save-dev eslint-plugin-react
.eslintrc 文件修改配置
...
"extends":[ "plugin:react/recommended" ],
...
"plugins":["react"],
...
"parserOptions":{
"ecmaFeatures":{"jsx": true},
},
....
支持 React Hooks 语法的一些规则
npm install --save-dev eslint-plugin-react-hooks
修改 .eslintrc 配置
...
"plugins":[ "react-hooks" ],
"rules":{
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
...
支持 jsx 语法的一些规则
npm install --save-dev eslint-plugin-jsx-a11y
修改 .eslintrc 配置
...
"plugins": ["jsx-a11y"],
"extends": ["plugin:jsx-a11y/recommended"],
"rules":{
"jsx-a11y/rule-name": 2,
...
}
使用 @typescript-eslint/parser 作为解析器,将 TypeScript 转换成与 estree 兼容的形式,以便在ESLint中使用
npm isntall --save-dev @typescript-eslint/parser
修改 .eslintrc 文件配置
...
"parser": "@typescript-eslint/parser"
...
安装 @typescript-eslint/eslint-plugin 插件,继承 typescript 的一些规则
npm install --save-dev @typescript-eslint/eslint-plugin
修改 .eslintrc 一些配置
...
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended"],
"rules":{
"@typescript-eslint/rule-name": "error",
...
},
...
完整的 .eslintrc 文件配置将在第四步中进行整理。
样式相关:css、less
CSS 相关
npm install --save-dev style-loader css-loader
图片资源
npm install --save-dev file-loader
字体等其他资源
npm install --save-dev url-loader
less 相关
npm install --save-dev less less-loader
react相关
本次只是样式如何搭建 react 项目的基础架构,因此像 路由、状态管理器等就不安装了。
npm install react react-dom --save
接口相关:axios、mock
npm install --save axios
mock的使用我决定用在后端 koa 项目中,所以先不安装。
UI库:antd
npm install --save antd
其他
安装 rimraf 用来使用代码删除文件或文件夹
npm install --save-dev rimraf
用法:
const rimraf = require('rimraf');
rimraf('./test.txt', function (err) {
console.log(err);
});
第三步:配置TypeScript(非必需,使用可以使项目利于维护和阅读)
在项目根目录创建 TypeScript 配置文件 tsconfig.json,文件内容基本如下:
{
"compilerOptions": {
"strictNullChecks": true,
"moduleResolution": "node",
"esModuleInterop": true,
"experimentalDecorators": true,
"jsx": "react",
"noUnusedParameters": true,
"noUnusedLocals": false,
//"noImplicitAny": false,
"target": "es6",
"lib": ["esnext", "dom"],
"module": "esnext",
"allowJs": true,
"noEmit": true,
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
//需要 typescript 编译的文件
"include": ["src/**/*"],
//过滤不需要编译的文件
"exclude": ["node_modules", "dist"]
}
具体的 compilerOptions 所包含的编译选项可参考官网的列表:https://www.tslang.cn/docs/handbook/compiler-options.html
第四步:设置eslint,进行代码规范
.eslintrc.js 文件配置内容:
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:jsx-a11y/recommended',
'plugin:@typescript-eslint/recommended',
],
env: {
browser: true,
es6: true,
commonjs: true,
node: true
},
plugins: ['react', 'react-hooks', 'jsx-a11y', '@typescript-eslint'],
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
globals: {},
rules: {
'no-console': 1,
'no-debugger': 1,
'no-irregular-whitespace': 0,
'no-unused-vars': 1,
'@typescript-eslint/indent': [0],
'@typescript-eslint/explicit-function-return-type': [0],
'@typescript-eslint/explicit-member-accessibility': [0],
'@typescript-eslint/camelcase': [0],
'@typescript-eslint/no-var-requires': [0],
'jsx-a11y/no-static-element-interactions': [0],
'jsx-a11y/click-events-have-key-events': [0],
'jsx-a11y/anchor-is-valid': [
'off',
{
components: ['Link'],
specialLink: ['hrefLeft', 'hrefRight'],
aspects: ['invalidHref'],
},
],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
// 以当前目录为根目录,不再向上查找 .eslintrc.js
root: true,
};
第五步:配置webpack
使用 webpack 4+ 版本
npm install --save-dev webpack webpack-cli
# 实现实时加载
npm install --save-dev webpack-dev-server
# 用来合并不同环境配置文件
npm install --save-dev webpack-merge
# 用来向 Html 模板中动态添加 webpack 输出的文件
npm install --save-dev html-webpack-plugin
# 清理 dist 文件夹
npm install --save-dev clean-webpack-plugin
配置webpack:
首先在项目根目录创建 config 和 src 两个文件夹,我们将 webpack 的配置文件放入 config 文件夹,src 目录用来保存我们的项目代码。
├─.babelrc
├─.eslintrc.js
├─package-lock.json
├─package.json
├─tsconfig.json
├─src
├─config
├─node_modules
在 config 文件夹下创建 webpack.common.js ,webpack.dev.js ,webpack.prod.js,template.html 文件,分别作为 webpack 的基础配置文件、开发环境配置文件,生产环境配置文件,html-webpack-plugin 插件使用的 html 模板文件。
# webpack.common.js
const path = require('path');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, '../dist')
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
quiet: true,
cache: true,
},
},
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
],
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
javascriptEnabled: true, // 解决antd样式加载问题,参考:https://github.com/ant-design/ant-motion/issues/44#issuecomment-407498459
// 所有样式变量: https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
modifyVars: {},
},
},
]
},
{
test: /\.(svg|png|jpg|gif|ico)$/,
loader: 'url-loader',
options: {
limit: 8192,
name: 'images/[name].[ext]'
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader'
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: '王习习测试项目',
template: path.join(__dirname, './template.html'),
})
]
}
# webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
mode: 'development',
devServer: {
contentBase: './dist',
hot: true,
https: true,
host: '127.0.0.1',
port: 8080,
open: true,
proxy:{}, //代理
historyApiFallback:{
disableDotRule:true
}
},
plugins:[
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin
]
});
# webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production'
});
# template.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<meta charset="UTF-8">
</head>
<body>
<div id="root"></div>
</body>
</html>
在 package.json 文件里添加 webpack 执行的相关 NPM 脚本
"scripts": {
......
"build": "webpack --config config/webpack.prod.js",
"dev": "webpack-dev-server --inline --progress --config config/webpack.dev.js"
},
第六步:创建 react 文件,启动项目
在 src 文件夹下创建入口文件 index.js
import React from 'react';
import ReactDom from 'react-dom';
ReactDom.render(
<div>王习习测试</div>,
document.getElementById('root')
);
在项目的 cmd 里执行之前设置的 NPM 脚本
npm run dev
会自动打开浏览器展示我们写好的项目页面