React 环境搭建
react除了jsx就是纯粹的js语法,不像vue一样进行模板解析。因此解析react就需要解析jsx => babel-loader
JSX预设 - @babel/preset-react
创建babel.config.json:
{
"presets": [
"@babel/preset-react"
],
}
配置webpack.config.js
let loaders = [
...loaders,
{
test: /\.(js|jsx)/,
include: [resolve(__dirname, 'src')],
use: ['babel-loader']
}
]
npx webpack 执行成功。注意这里没有给 具体的react代码出来,需要注意的事,
- js文件里使用了jsx语法需要手动的引入 React
- 挂载的DOM在template html上必须拥有,即如果你的html没有 root,检查一下是否需要手动创建
@babel/preset-react 预设有options:
- runtime:'classic' | 'automatic',不需要指定 import React 才当 载入 JSX转换函数
- automatic 下
- importSource 是否自动导入React
- classic 下
- pragma:遇到JSX使用 React.createElement 替换解析
- pragmaFrag:遇到 Fragment 或者 <> 使用 React.Fragment 替换解析
- useBuiltIns:是否需要polyfill
- useSpread:当使用jsx展开对象语法的时候,是否 使用 babel 或者 Object.assign 去做一层 polyfill,默认是用polyfill
React 添加 自动热更新
React每个组件的自动隔离的,并且在导入的时候编译 出 module.hot.accept 实现热更新,我们需要做两件事:
-
babel 需要添加额外代码,说明需要使用更多插件:react-refresh
{ "presets": [ "@babel/preset-react" ], "plugins": [ "react-refresh/babel" ] } -
需要使用 plugin,模块替换之后和浏览器的交互
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); let plugins = [ ...plugins, new ReactRefreshWebpackPlugin() ]
Create-React-App是怎么做的
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
// 主要使用 babel-preset-react-app 插件预设
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
presets: [
// 这其实就是官网的 react-app,requirexxx是能更快一点
[
require.resolve('babel-preset-react-app'),
{
runtime: hasJsxRuntime ? 'automatic' : 'classic',
},
],
],
plugins: [
isEnvDevelopment &&
shouldUseReactRefresh &&
require.resolve('react-refresh/babel'),
].filter(Boolean),
// ....
},
},
// 外部的一些js文件
{
test: /\.(js|mjs)$/,
exclude: /@babel(?:\/|\\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
// .....
},
},
而且其实 Create-React-App 在 resolve.plugins 的内部做了一些东西:
resolve.plugins = [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc, [
paths.appPackageJson,
reactRefreshRuntimeEntry,
reactRefreshWebpackPluginRuntimeEntry,
babelRuntimeEntry,
babelRuntimeEntryHelpers,
babelRuntimeRegenerator,
]),
]