React环境搭建

250 阅读2分钟

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,
  ]),
]