接上篇......
十一、集成JSX语法
1、安装react
bash
cnpm i react -S
cnpm i react-dom -S
说明:
(1)-S是代码需要的包,-D是环境需要的包
(2)react-dom是用于挂载的
(3)react作用是用来封装组件的
2、建立react根组件
在src/App.jsx
javascript
import React from 'react'
class App extends React.Component {
render() {
return (
<div>
<h1>Hello React</h1>
</div>
)
}
}
export default App
3、main.js创建挂载节点
javascript
// 入口文件
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
const root = createRoot(document.getElementById('app'))
root.render(<App />)
4、babel安装react预设
bash
cnpm i @babel/preset-react -D
babel.config.js:
javascript
// 定义babel的工作方式
module.exports = {
// 预设:用于编译哪些比较大的JS版本,比如ES6、TS、Flow、Vue等
presets: [
'@babel/preset-env',
'@babel/preset-react' // 用于编译JSX语法
],
// 插件
plugins: [
// 这个插件用于编译装饰器语法
["@babel/plugin-proposal-decorators", { "version": "2023-11" }]
]
}
5、babel-loader增加jsx配置
config.js:
javascript
// 两个环境都需要的公共配置
// 从node进程中引入path模块
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ProgressPlugin } = require('webpack') // webpack自带插件
module.exports = {
entry: {
// 可以给入口文件取个名字,给output使用
app: path.resolve(__dirname, '../', 'src/main.js'),
},
// 出口
output: {
// 自定义打包结果的输出目录,默认是dist目录,这里只能使用绝对路径
path: path.resolve(__dirname, '../', 'dist'),
// 指定打包结果的JS名称规范
// filename: 'bundle.js' // 量词,一捆、一束
filename: 'js/[name].[chunkhash:8].js',
// 每次build打包时,都自动先删除dist中的旧文件
clean: true
},
// 插件
// 所有webpack插件都是class,用的时候需要new
plugins: [
// 用于把JS脚本和index.html自动注入合并
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../', 'public/index.html'),
inject: 'body', // 把JS注入到body结束标签前面
filename: 'index.html', // 指定打包成功后这个模板叫什么名字
title: '测试'
}),
// 添加编译进度条
new ProgressPlugin({
handler(percentage, message, ...args) {
console.log(percentage, message, ...args)
}
})
],
// 在webpack眼中一切文件皆模块,webpack必须使用各种loaders来处理各种不同的模块文件
module: {
// 定义模块编译的规则和方式
rules: [
{
test: /\.(js|jsx|ts|tsx)$/, // 检测模块以js结尾
use: ['babel-loader'] // 使用babel编译器把ES6+的代码编译成ES5
}
]
}
}
修改:test: /\.(js|jsx|ts|tsx)$/, // 检测模块以js结尾
6、解决报错信息是编译后的行数

希望调试控制台中报错的位置和src源码位置保持一致。
serve.js:
javascript
// 只有开发环境才需要用到配置
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
// 本地服务配置
devServer: {
port: 8000
}
}
build.js:
javascript
// 只有打包时才用到配置
module.exports = {
mode: 'production',
devtool: 'source-map'
}
重启服务,这时报错信息行数变成代码的行数了,而不是编译后的行数:


调试控制台:
inline-source-map
打包环境:
source-map
7、解决react没有导入问题
问题:为什么react没有导入?凡是用到JSX的地方,都要导入react
临时解决:import React from 'react'
背后原理:
(1)因为我们用到了jsx语法,jsx要编译成js代码,浏览器才能看的懂
(2)@babel/preset-react它要使用React.createElement()方法进行编译
(3)以后新建jsx文件天天都要导入吗?
(4)把React放在window上,全局上
8、把React放在全局上
使用内置插件ProvidePlugin
config.js:
javascript
// 两个环境都需要的公共配置
// 从node进程中引入path模块
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { ProgressPlugin, ProvidePlugin } = require('webpack') // webpack自带插件
module.exports = {
entry: {
// 可以给入口文件取个名字,给output使用
app: path.resolve(__dirname, '../', 'src/main.js'),
},
// 出口
output: {
// 自定义打包结果的输出目录,默认是dist目录,这里只能使用绝对路径
path: path.resolve(__dirname, '../', 'dist'),
// 指定打包结果的JS名称规范
// filename: 'bundle.js' // 量词,一捆、一束
filename: 'js/[name].[chunkhash:8].js',
// 每次build打包时,都自动先删除dist中的旧文件
clean: true
},
// 插件
// 所有webpack插件都是class,用的时候需要new
plugins: [
// 用于把JS脚本和index.html自动注入合并
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../', 'public/index.html'),
inject: 'body', // 把JS注入到body结束标签前面
filename: 'index.html', // 指定打包成功后这个模板叫什么名字
title: '测试'
}),
// 添加编译进度条
new ProgressPlugin({
handler(percentage, message, ...args) {
console.log(percentage, message, ...args)
}
}),
// 从node_modules中加载react包,将其放在全局变量React中,这样之后所有的文件模块都可以直接访问
new ProvidePlugin({
React: 'react'
}),
],
// 在webpack眼中一切文件皆模块,webpack必须使用各种loaders来处理各种不同的模块文件
module: {
// 定义模块编译的规则和方式
rules: [
{
test: /\.(js|jsx|ts|tsx)$/, // 检测模块以js结尾
use: ['babel-loader'], // 使用babel编译器把ES6+的代码编译成ES5
exclude: /node_modules/, // 排除node_modules目录下的第三方包文件
}
]
}
}
exclude: /node_modules/, // 排除node_modules目录下的第三方包文件