从零开始使用webpack搭建一个react项目

news2024/10/7 8:31:21

先做一个正常编译es6语法的webpack demo

1. 初始化package.json文件

npm init一路enter下去

2. 添加插件

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "devBuild": "cross-env NODE_ENV=development webpack --config build-splitChunks-react/webpack.config.js",
    "start:dev": "cross-env NODE_ENV=development webpack-dev-server --config build-splitChunks-react/webpack.config.js",
    "start:prod": "cross-env NODE_ENV=production webpack-dev-server --config build-splitChunks-react/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config build-splitChunks-react/webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
    "@babel/preset-env": "^7.22.20",
    "@babel/preset-react": "^7.22.15",
    "@babel/preset-typescript": "^7.23.0",
    "@reduxjs/toolkit": "^1.9.7",
    "@types/react": "^18.2.27",
    "@types/react-dom": "^18.2.12",
    "autoprefixer": "^9.7.3",
    "axios": "^1.5.1",
    "babel-core": "^7.0.0-bridge.0",
    "babel-loader": "7",
    "babel-preset-env": "^1.7.0",
    "clean-webpack-plugin": "^3.0.0",
    "cross-env": "^7.0.3",
    "css-loader": "^3.2.1",
    "file-loader": "^5.0.2",
    "happypack": "^5.0.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.10.3",
    "less-loader": "5.0.0",
    "mini-css-extract-plugin": "^0.8.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "react-redux": "^8.1.3",
    "redux": "^4.2.1",
    "redux-persist": "^6.0.0",
    "style-loader": "^1.0.1",
    "terser-webpack-plugin": "^2.2.2",
    "typescript": "^5.2.2",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.9.0",
    "webpack-merge": "^4.2.2",
    "webpack-parallel-uglify-plugin": "^1.1.2"
  },
  "dependencies": {
    "antd": "^5.10.0",
    "lodash": "^4.17.15",
    "moment": "^2.24.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

注意: babel相关插件最好是同一个数字版本开头的, 比如7.xx.xx, 因为页面报babel-loader编译问题, 提示是版本不一致

另外因为我使用了redux, 复杂的项目可以使用它, 简单的项目context或者recoil就行了, 按需下载, 不需要的可以卸载

3. react多页配置

1) webpack.common.js拆分公共部分

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
    entry: {
        index: path.join(srcPath, 'index.tsx'),
        other: path.join(srcPath, 'other.tsx')
    },
    resolve: {
        extensions: ['.tsx', '.ts', '.jsx', '.js']
    },
    module: {
        rules: [
            {
                test: /.(jsx?)|(ts?x?)$/,
                loader: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/
            },
        ]
    },
    plugins: [
        // 多入口 - 生成 index.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html',
            // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
            chunks: ['index', 'vendor', 'common']  // 要考虑代码分割
        }),
        // 多入口 - 生成 other.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'other.html'),
            filename: 'other.html',
            chunks: ['other', 'common']  // 考虑代码分割
        })
    ]
}

2) webpack.dev.js:

dev环境需要的webpack配置, 注意与webpack.common.js的逻辑进行合并

const path = require('path')
const webpack = require('webpack')
const webpackCommonConf = require('./webpack.common.js')
const { smart } = require('webpack-merge')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'development',
    module: {
        rules: [
            // 直接引入图片 url
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: 'file-loader'
            },
            {
                test: /\.css$/,
                // loader 的执行顺序是:从后往前
                loader: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
            },
            {
                test: /\.less$/,
                // 增加 'less-loader' ,注意顺序
                loader: ['style-loader', 'css-loader', 'less-loader']
            }
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // 'development'
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        })
    ],
    devServer: {
        port: 8111,
        progress: true,  // 显示打包的进度条
        contentBase: distPath,  // 根目录
        open: true,  // 自动打开浏览器
        compress: true,  // 启动 gzip 压缩
        // 设置代理
        proxy: {
            // 将本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:8000',

            // 将本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:8111',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    }
})

3) webpack.production.js:

production环境需要的webpack配置, ,注意与webpack.common.js的逻辑进行合并

const path = require('path')
const webpack = require('webpack')
const { smart } = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const webpackCommonConf = require('./webpack.common.js')
const { srcPath, distPath } = require('./paths')

module.exports = smart(webpackCommonConf, {
    mode: 'production',
    output: {
        // filename: 'bundle.[contentHash:8].js',  // 打包代码时,加上 hash 戳
        filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
        path: distPath,
        // publicPath: 'http://cdn.abc.com'  // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
    },
    module: {
        rules: [
            // 图片 - 考虑 base64 编码的情况
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的图片用 base64 格式产出
                        // 否则,依然延用 file-loader 的形式,产出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目录下
                        outputPath: '/img1/',

                        // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },
            // 抽离 css
            {
                test: /\.css$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,这里不再用 style-loader
                    'css-loader',
                    'postcss-loader'
                ]
            },
            // 抽离 less
            {
                test: /\.less$/,
                loader: [
                    MiniCssExtractPlugin.loader,  // 注意,这里不再用 style-loader
                    'css-loader',
                    'less-loader',
                    'postcss-loader'
                ]
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(), // 会默认清空 output.path 文件夹
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify(process.env.NODE_ENV)
            }
        }),

        // 抽离 css 文件
        new MiniCssExtractPlugin({
            filename: 'css/main.[contentHash:8].css'
        })
    ],

    optimization: {
        // 压缩 css
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],

        // 分割代码块
        splitChunks: {
            chunks: 'all',
            /**
             * initial 入口 chunk,对于异步导入的文件不处理
                async 异步 chunk,只对异步导入的文件处理
                all 全部 chunk
             */

            // 缓存分组
            cacheGroups: {
                // 第三方模块
                vendor: {
                    name: 'vendor', // chunk 名称
                    priority: 1, // 权限更高,优先抽离,重要!!!
                    test: /node_modules/,
                    minSize: 0,  // 大小限制
                    minChunks: 1  // 最少复用过几次
                },

                // 公共的模块
                common: {
                    name: 'common', // chunk 名称
                    priority: 0, // 优先级
                    minSize: 0,  // 公共模块的大小限制
                    minChunks: 2  // 公共模块最少复用过几次
                }
            }
        }
    }
})

4) 可以再加一个webpack.config.js文件:

根据环境判断是使用webpack.dev.js还是webpack.production.js

const prodConfig = require('./webpack.prod.js');

const webpackConfig = process.env.NODE_ENV !== 'development' ? prodConfig : () => import('./webpack.dev.js');
module.exports = webpackConfig;

5) 在package.json添加如下命令:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config build-splitChunks-react/webpack.config.js",
    "buil:debv": "cross-env NODE_ENV=development webpack --config build-splitChunks-react/webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config build-splitChunks-react/webpack.config.js"
  },
cross-env改变process.env.NODE_ENV的值, 在控制台可以打印出来

console.log(process.env.NODE_ENV);

4. 新建index.html, index.tsx, other.html, other.tsx文件

index.tsx文件

// index.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
/**
 * 不加后缀.tsx的配置: 在module.exports对象中追加=>
 * resolve: {
        extensions: ['.js', '.jsx', '.tsx', '.ts']
    },
 */
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
// v18 的新方法
root.render(<App />)

index.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>webpack demo</title>
</head>
<body>
    <p>webpack demo</p>
    <div id="root"></div>
</body>
</html>

other.tsx和other.html差不多一样按react要求写, 写出差异页面能够看出是不同页面就行

5. 新建.babelrc文件

{
    "presets": [
        "@babel/preset-react", 
        "@babel/preset-typescript",
    ],
    "plugins": []
}

6. 新建postcss.config.js文件

module.exports = {
    plugins: [require('autoprefixer')]
}

7. 新建tsconfig文件

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "noImplicitAny": false
  },
  "include": [
    "src"
  ]
}
  

5. Test组件

import React, { useEffect, useState } from "react";
import _ from "lodash";

const Test = () => {
  const [data, setData] = useState({ a: "hello world" });
  useEffect(() => {
    setData({ a: "gggg" });
    console.log("process", process.env.NODE_ENV, process.env);
  }, []);
  return <div>{_.get(data, "a")}</div>;
};

export default Test;

6. 在App.tsx组件中引入Test组件测试效果

import React, { Suspense, lazy } from "react";
import { Spin } from "antd";
import Test from "./Test";

const App: React.FC = () => {
  return (
    <Suspense fallback={<Spin />}>
      <Test />
    </Suspense>
  );
};

export default App;

index.html效果图如下:

other.html效果图如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1089593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot利用CompletableFuture异步执行线程(有回调和无回调)

目录 背景 实现 一、异步线程配置类 二、自定义异步异常统一处理类 三、实现调用异步&#xff08;无回调-runAsync()&#xff09; 四、实现调用异步&#xff08;有回调-supplyAsync()&#xff09; 五、异步执行错误异常示例 背景 项目中总会有需要异步执行来避免浪费…

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理

Windows中将tomcat以服务的形式安装,然后在服务进行启动管理 第一步&#xff1a; 在已经安装好的tomcat的bin目录下&#xff1a; 输入cmd&#xff0c;进入命令窗口 安装服务&#xff1a; 输入如下命令&#xff0c;最后是你的服务名&#xff0c;避免中文和特殊字符 service.…

Redis数据类型及命令

目录 &#xff08;一&#xff09;通用命令&#xff08;二&#xff09;String类型&#xff08;三&#xff09;Hash类型&#xff08;四&#xff09;List类型&#xff08;五&#xff09;Set类型&#xff08;六&#xff09;SortedSet类型 在redis命令行查询redis通用命令&#xff1…

如何使用摩尔信使MThings连接网络设备

帽子&#xff1a; 摩尔信使MThings支持Modbus-TCP、Modbus-RTU Over TCP、Modbus-TCP Over UDP、Modbus-RTU Over UDP。 TCP链接中&#xff0c;摩尔信使MThings支持灵活的连接方式&#xff0c;主机可作为客户端也可以作为服务端&#xff0c;同时支持模拟从机以客户端方式向远…

1600*C. Add One(数位DP找规律)

Problem - 1513C - Codeforces 解析&#xff1a; 考虑DP&#xff0c;DP[ i ] 为从 0 开始执行 i 次操作&#xff0c;此时数字的位数。 我们发现当一个9再操作一次就会变成1和0&#xff0c;并且相邻的大部分长度都不会变化&#xff0c;0会影响10次操作之后的位数&#xff0c;1会…

开源自动化测试框架优缺点对比

1. Robot Framework Robot Framework&#xff08;RF&#xff09;是用于验收测试和验收测试驱动开发&#xff08;ATDD&#xff09;的自动化测试框架。 基于 Python 编写&#xff0c;但也可以在 Jython&#xff08;Java&#xff09;和 IronPython&#xff08;.NET&#xff09; 上…

网页版微信CRM系统,让微信管理更方便!

微信&#xff0c;作为现在热门的社交软件之一&#xff0c;已经成为商家和消费者交流的主要渠道。但对于客服这类人群来说&#xff0c;一个得管理多个微信号&#xff0c;耗费了他们大量时间精力。 因此&#xff0c;微信CRM 系统应运而生。它可以将多个微信聚合在一个界面中&…

PPO算法逐行代码详解

前言&#xff1a;本文会从理论部分、代码部分、实践部分三方面进行PPO算法的介绍。其中理论部分会介绍PPO算法的推导流程&#xff0c;代码部分会给出PPO算法的各部分的代码以及简略介绍&#xff0c;实践部分则会通过debug代码调试的方式从头到尾的带大家看清楚应用PPO算法在car…

三、静态路由实验

拓扑图&#xff1a; 两个路由器分了三个网段出来&#xff0c;首先对两台PC机进行配置 进入R1路由器对两边链路进行ip配置 对AR2进行相同的配置&#xff0c;然后我们查看R1的路由表&#xff0c;里面有一些直连的信息。 三个网段的设备现在可以互通&#xff0c;我们要实现跨网段…

[数据结构]——单链表超详细总结

带你走进链表的世界 目录&#xff1a;一、线性表的概念二、顺序表三、链表3.1 链表的概念3.2 链表的分类3.3 无头单向非循环链表的实现3.4 带头双向循环链表的实现 四、顺序表和链表的区别和联系 目录&#xff1a; 链表是个优秀的结构&#xff0c;没有容量概念&#xff0c;可以…

Python接口测试 requests.post方法中data与json参数区别

引言 requests.post主要参数是data与json&#xff0c;这两者使用是有区别的&#xff0c;下面我详情的介绍一下使用方法。 Requests参数 1. 先可以看一下requests的源码&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 13 def post(url, dataNone, jsonNone, **kwargs): r&quo…

STM32CUBEMX_DMA串口空闲中断接收+接收发送缓冲区

STM32CUBEMX_DMA串口空闲中断接收接收发送缓冲区 前言&#xff1a; 我了解的串口接收指令的方式有&#xff1a;在这里插入图片描述 1、接收数据中断特定帧尾 2、接收数据中断空闲中断 3、DMA接收空闲中断 我最推荐第三种&#xff0c;尤其是数据量比较大且频繁的时候 串口配置 …

Vmware Linux虚拟机安装教程(Centos版)

文章目录 1.Vmware-workstation安装软件2.双击下载的安装包开始安装3.打开VMware-workstation&#xff0c;输入密钥4.Centos7.6安装软件5.新建虚拟机6.为虚拟机配置映像文件7.开启虚拟机&#xff0c;配置环境7.1 Install Centos 77.2 选择简体中文字体7.3 软件选择7.4 安装位置…

LeetCode【20】 有效的括号

题型&#xff1a;栈 题目&#xff1a; 代码&#xff1a; public boolean isValidReview(String s) {//&#xff08;1&#xff09;从s的i0位置一次开始压栈&#xff0c;遇到左括号压栈&#xff0c;不管是大中小三种&#xff0c;左括号&#xff0c;压//&#xff08;2&#xf…

基于 EventBridge 轻松搭建消息集成应用

作者&#xff1a;昶风 前言 本篇文章主要介绍基于阿里云 EventBridge 的消息集成能力&#xff0c;结合目前消息产品的需求热点&#xff0c;从能力范围到场景实战&#xff0c;对 EventBridge 的消息集成解决方案进行了概要的介绍。 从消息现状谈起 消息队列作为应用解耦&…

Redis 基础—Redis Desktop Manager(Redis可视化工具)安装及使用教程

Redis Desktop Manager 是一个可视化的 Redis 数据库管理工具&#xff0c;可以方便地查看和操作 Redis 数据库。使用 Redis Desktop Manager 可以大大提高 Redis 数据库的管理效率。 RDM的安装和配置 首先&#xff0c;您需要下载和安装Redis Desktop Manager。 安装完成后&am…

高校教务系统密码加密逻辑及JS逆向——皖南医学院

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

提升企业服务行业管理效率的关键策略与方法」

To B 服务&#xff0c;也即企业服务近年来大家关注的重点&#xff0c;企业服务是指为企业客户提供运营管理相关的工具与系统解决方案等服务&#xff0c;通过专业化的服务可以实现降本增效&#xff0c;提高企业的经营效率。 近年来&#xff0c;人口红利的消失促使企业服务需求快…

DC电源模块低温是否影响转换效率

BOSHIDA DC电源模块低温是否影响转换效率 DC电源模块是一种常用的电源转换装置&#xff0c;其主要作用是将输入的电源信号变换成需要的输出电源信号。在实际应用中&#xff0c;DC电源模块的性能会受到多种因素的影响&#xff0c;其中低温也是一个重要的影响因素。本文将从转换…

kettle应用-从数据库抽取数据到excel

本文介绍使用kettle从postgresql数据库中抽取数据到excel中。 首先&#xff0c;启动kettle 如果kettle部署在windows系统&#xff0c;双击运行spoon.bat或者在命令行运行spoon.bat 如果kettle部署在linux系统&#xff0c;需要执行如下命令启动 chmod x spoon.sh nohup ./sp…