乐趣区

手工创建react项目

react的开发者都知道使用 create-react-app 创建项目,这是非常简单的,但不是本文的目的,本文将带你如何一步一步搭建 react 项目。

1、初始化项目,编写组件

执行下面命令初始化项目

npm init -y

安装react、react-dom

npm -i -D react react-dom

在根目录下创建 src 文件夹,并在 src 文件夹里面创建 index.js、index.css 文件,他们两分别是组件和组件所需样式

// index.js
import React, {Component} from 'react'
import ReactDOM from 'react-dom'

import './index.css'

class App extends Component {
  // 类属性写法是 js 实验特性
  state = {textInput: null}

  textInputFocus = (element) => {this.textInput = element}
  // 此箭头函数写法是 js 实验特性
  handleClick = () => {this.textInput.focus()
  }

  render () {
    return (
      <div className="div-box">
        <input type="text" ref={this.textInputFocus}/>
        <input type="button" value="focus" onClick={this.handleClick}/>
      </div>
    )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
)
// index.css
.div-box {
  width: 500px;
  height: 500px;
  border: 1px solid #000;
  box-sizing: border-box;
}

2、配置 webpack+babel

浏览器是不支持 JSX 语法,而且上面 index.js 中还是用了 js 实验特性,目前还没有被 ECMAScript 所采纳,也是需要 babel 转译。我们还需要处理 css 样式或者其他样式规格,最后打包成 js 引入到生成的 html 文件中。

安装相关依赖:

npm i -D webpack 
webpack-cli 
webpack-dev-server 
@babel/core 
@babel/plugin-proposal-class-propertiese 
@babel/cli 
@babel/preset-env 
@babel/preset-react
@babel/runtime 
@babel/plugin-transform-runtime 
babel-loader 
css-loader 
style-loader 
html-webpack-plugin 
clean-webpack-plugin

对其中有些依赖做个说明,webpack-dev-server帮助我们实时打包文件,只要文件改动就重新打包。@babel/plugin-proposal-class-propertiese转译 js 实验特性,比如类里面定义的属性和箭头函数。@babel/preset-react帮助转译 JSX 语法。html-webpack-plugin帮助生成 html,并将打包后的js 引入。clean-webpack-plugin每次打包都会将上次打包的文件清除。
链接:https://www.npmjs.com/package/@babel/plugin-proposal-class-properties

在根目录下创建 webpack.config.js 配置webpack

const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: {app: './src/index.js'},
  output: {path: path.resolve(__dirname, 'build'),
    filename: '[name].bundle.js',
    publicPath: './',
    chunkFilename: '[name].js'
  },
  module: {
    rules: [
      // 处理 js、jsx
      {test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [{loader: 'babel-loader'}]
      }, 
      // 处理样式
      {
        test: /\.css$/,
        use: [
          {loader: 'style-loader'},
          {loader: 'css-loader'}
        ]
      }
    ]
  },
  optimization: { },
  plugins: [new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: '主文件',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        minifyCSS: true
      },
      filename: 'index.html',
      template: path.resolve(__dirname, 'index.html'),
      chunks: ['app']
    })
  ]
}

在根目录下创建 .babelrc 配置babel

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
    "@babel/plugin-proposal-class-properties" // 该插件可转换静态类属性以及使用属性初始值设定项语法声明的属性
  ]
}

在根目录下创建 idnex.html 模板

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
  <div id="app"></div>
</body>
</html>

3、配置 eslint

安装依赖

npm i -D eslint

执行 npx eslint --init 在根目录下生成 .eslintrc.js 配置文件,交互生成过程中选择react

如果现在去校验 src 目录文件的代码规范将会报错,因为目前 eslint 只支持 ES6/ES2015,不支持spread object 语法,经查发现 spread objectES7规范(还包括class properties,decorators,async/await

这条错误指的是

安装babel-eslint

npm install babel-eslint --save-dev

倘若需要支持 generator-star,object-shorthand 等特性,需要安装eslint-plugin-babel

npm install eslint-plugin-babel --save-dev

然后在配置文件.eslintrc.\* 添加如下配置

module.exports = {
  env: {
    browser: true,
    es6: true
  },
  extends: ['standard',],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly'
  },
  parser: "babel-eslint",
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
      experimentalObjectRestSpread: true
    },
    ecmaVersion: 2018,
    sourceType: 'module'
  },
  plugins: [
    'react',
    'babel'
  ],
  rules: {},}

现在检查代码规范将报如下错误:

解决方法

extends: [
    'standard',
    'plugin:react/recommended' // 添加 react 插件推荐规则
],

或者在 rule 中添加如下重写如下规则:

rules: {
    "react/jsx-uses-react": 1, // 处理组件中 React 未被使用
    "react/jsx-uses-vars": 1 // 使用组件 App 未被使用
  },

再次检查代码规范又会报一条警告:

React version not specified in eslint-plugin-react settings

说在 eslint-plugin-react中没有指定 react 版本

这里我们通过给所有规则配置共享设置来解决:

如何添加共享设置:https://eslint.org/docs/user-guide/configuring#adding-shared-settings

.eslintrc.js 加上下面设置

settings: {
    react: {
      // 修复警告:React version not specified in eslint-plugin-react settings
      version: require('./package.json').devDependencies.react
    }
  }

最后,为了运行方便,我们在 package.json 中添加脚本

"scripts": {
    "build": "webpack --mode production",
    "start": "webpack-dev-server --open",
    "lint": "eslint ./src",
    "lint:watch": "esw -w ./src"
},

其中,配置 lint:watch 需要先安装 eslint-watch 插件,该插件帮助我们实时检测代码规范,就跟 webpack-dev-server 帮助我们启动服务实时打包一样。

现在我们来打包运行看看:

浏览器打开生成的index.html

执行 eslint 看看

简直完美!

参考:
如何创建 react 项目:
https://mingjiezhang.github.io/2017/06/16/%E7%BF%BB%E8%AF%91-%E6%80%8E%E4%B9%88%E5%86%99%E4%B8%80%E4%B8%AAReact%E7%BB%84%E4%BB%B6%E5%BA%93%EF%BC%88%E4%B8%80%EF%BC%89/
https://dev.to/vish448/create-react-project-without-create-react-app-3goh
eslint 如何支持 ES7 语法校验
https://github.com/garylgh/blog/blob/master/source/_posts/Eslint%E5%BC%80%E5%90%AFES7%E8%AF%AD%E6%B3%95%E6%A0%A1%E9%AA%8C.md
组件中 React 导入了但没有被使用,eslint 检测报错
https://github.com/babel/babel-eslint/issues/6
修复警告:React version not specified in eslint-plugin-react settings
https://github.com/yannickcr/eslint-plugin-react/issues/1955

源代码:https://github.com/Revelation2019/create-react-project

退出移动版