【React】自定义搭建react脚手架(开发环境)

自定义搭建react脚手架(开发环境)


前言

create-react-app太过笨重了,自己手动搭建一个脚手架。本篇介绍开发环境的搭建。

需要实现如下功能:

  • 能执行react代码
  • 能在不引入React的情况下解析JSX
  • 使用webpack打包
  • 能启动开发服务
  • 能实现HMR
  • 能生成Html模板
  • 能处理cssless,并实现样式兼容
  • 能解析js代码
  • 能实现代码自动检查
  • 够快

下面就来一一实现。


准备

创建一个custom_react文件夹,作为根目录。

创建文件.gitignore

mode_modules

初始化生成package.json

npm init -y

根目录下创建src文件夹,分别写入如下文件:

// index.js
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const root = createRoot(document.getElementById("root"));

root.render(
    <StrictMode>
        <App />
    </StrictMode>
);
// App.jsx

import { useState } from 'react';
import './app.less';

const App = () => {

    const [count, setCount] = useState(0);
    const [val, setVal] = useState('');

    return (
        <>
            <h3>Hello React18 !</h3>
            <button className='btn'
                onClick={() => {setCount(count + 1)}}
            >click me {count} times.</button>
            <div className='flex_box'>
                <input type="text" value={val} onChange={e=> {setVal(e.target.value)}} />
            </div>
        </>
    )
}

export default App;
/* app.less */
.btn {
    margin-top: 30px;
}

.flex_box {
    display: flex;
    width: 300px;
    height: 300px;
    box-sizing: border-box;
    border: 2px solid pink;
    border-radius: 10px;
    justify-content: center;
    align-items: center;
    margin-top: 20px;
}

根目录下创建public文件夹,并写入如下文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React App</title>
</head>
<body>
    <noscript>
        You need to enable javascript to run this app.
    </noscript>
    <div id="root"></div>
</body>
</html>

实现

下面来一步步实现需求。

第一个,能执行react代码

安装

npm i react react-dom -D

第三个,使用webpack打包
安装

npm i webpack webpack-cli -D

第四个,能启动开发服务

安装

npm i webpack-dev-server -D

下面是对接下来功能实现中需要用到的插件/库的安装和介绍:

// 实现HMR
npm i @pmmmwh/react-refresh-webpack-plugin react-refresh -D

// 生成html模板
npm i html-webpack-plugin -D

// 处理css
npm i style-loader css-loader -D

// css兼容
npm i postcss postcss-loader postcss-preset-env -D

// 处理less
npm i less less-loader -D

// babel相关
// babel的核心库
npm i @babel/core -D 
// babel环境预设
npm i @babel/preset-dev -D
// 辅助函数核心库
npm i core-js -D
// react预设
npm i @babel/preset-react -D
// 辅助函数运行时转换插件
npm i @babel/plugin-transform-runtime -D
npm i @babel/runtime
npm i @babel/runtime-corejs3 -D

// eslint代码检查
npm i eslint eslint-webpack-plugin -D

// 初始化生成eslint配置文件
npx eslint --init

配置介绍

babel.config.js

module.exports = {
    presets: [
        [
            "@babel/preset-env", // 环境预设
            {
                useBuiltIns: "usage", // 只打包用到的辅助函数
                corejs: { // 辅助函数核心库
                    version: "^3.29.1", // core-js的版本号
                    proposals: true
                }
            }
        ],
        [
            "@babel/preset-react", // react预设
            {
                // runtime配置非常重要
                // 设置为automatic会自动解析jsx代码的引入
                // 配置后就会自动运行jsx-runtime,无需手动引入React了
                runtime: "automatic"
            }
        ]
    ],
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
                corejs: 3, // @babel/runtime-corejs3的版本号
                version: "^7.21.0" // @babel/runtime的版本号
            }
        ]
    ]
}

postcss.config.js

module.exports = {
    plugins: [
        "postcss-preset-env" // postcss预设,会自动补充css前缀等
    ]
}

webpack.dev.js

const path = require("path");
const ReactRefreshPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const EslintWebpackPlugin = require("eslint-webpack-plugin");

const cssRules = /\.css$/; // 匹配css
const lessRules = /\.less$/; // 匹配less

// 抽取公共部分
const getStyleOptions = (importLoaders, loader) => {
    return [
        "style-loader",
        {
            loader: "css-loader",
            options: {
                importLoaders
            }
        },
        "postcss-loader",
        loader
    ].filter(Boolean);
}

module.exports = {
    // 开发环境
    mode: "development",
    // 入口
    entry: "./src/index.js",
    // 配置loader
    module: {
        rules: [
            {
                // oneOf可以提供精准解析
                oneOf: [
                    {
                        test: cssRules,
                        use: getStyleOptions(1)
                    },
                    {
                        test: lessRules,
                        use: getStyleOptions(2, "less-loader")
                    },
                    {
                        test: /\.jsx?$/,
                        exclude: /node_modules/,
                        use: {
                            loader: "babel-loader",
                            options: {
                                // 开启缓存
                                cacheDirectory: true,
                                // 关闭压缩
                                cacheCompression: false
                            }
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        // 生成html模板
        new HtmlWebpackPlugin({
            // 以index.html文件为模板
            template: path.resolve(__dirname, "public/index.html")
        }),
        // 开启HMR功能
        new ReactRefreshPlugin(),
        // 开启eslint检查
        new EslintWebpackPlugin({
            // 检查jsx js json文件
            extensions: ["jsx", "js", "json"],
            // 只对修改内容的文件做检查
            lintDirtyModulesOnly: true,
            // 开启多线程
            threads: true
        })
    ],
    // 开启source-map,精准定位错误代码
    devtool: "cheap-module-source-map",
    // 开启开发服务器
    // hot: true是默认的,无需重复配置
    devServer: {
    	// 启动端口号为3001
        port: 3001,
        // 启动服务后自动打开浏览器
        open: true
    },
    resolve: {
        // 扩展文件名,引入时不需要写后缀
        extensions: [".jsx", ".js", ".json"]
    }
}

.eslintrc.js

module.exports = {
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        // 配置jsx-runtime后,不引入React也不会报错了
        "plugin:react/jsx-runtime"
    ],
    "overrides": [
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
    }
}

package.json中添加启动项

"start": "webpack serve --config ./webpack.dev.js"

测试

根目录下打开终端,执行npm start

启动后就可以看到
在这里插入图片描述
App.jsx文件中,把Hello React18改为Hello React,然后在控制台打印666,按钮再点击几下,输入框里输入内容,保存文件,可以看到
在这里插入图片描述
修改的内容变化了,点击按钮的次数和输入框的内容都还在,控制台打印内容还在,控制台中也显示出了[HMR]...修改文件的提示,.less样式显示正常,说明我们的配置没问题,HMR也实现了。


开源

https://gitee.com/guozia007/custom_react
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值