webpack構(gòu)建自定義react應用


在上一篇文章中我們用webpack與webpack-cli搭建了最簡單的前端應用,通常在項目中我們會用vue或者react,我們看下如何利用我們自己搭的工程來適配react

正文開始...

前置
首先我們要確定,react并不是在webpack中像插件一樣安裝就可以直接使用,我們需要支持jsx以及一些es6的一些比較新的語法,在creat-react-app這個腳手架中已經(jīng)幫我們高度封裝了react項目的一些配置,甚至你是看不到很多的配置,比如@babel/preset-react轉(zhuǎn)換jsx等。所以我們需要知道一個react項目需要哪些插件的前提條件,本文主要參考從頭開始打造工具鏈[1]

安裝babel相關(guān)插件

npm i @babel/core @babel/cli @babel/preset-env @babel/preset-react --save
其中babel/core就是能將代碼進行轉(zhuǎn)換,@babel/cli允許命令行編譯文件,babel/preset-env與@babel/preset-react[2]都是預設(shè)環(huán)境,把一些高級語法轉(zhuǎn)換成es5

安裝好相關(guān)插件后,我們需要在根目錄中創(chuàng)建一個.babelrc來讓babel通知那兩個預設(shè)的兩個插件生效

// .babelrc
{
  "presets": ["@babel/env", "@babel/preset-react]
}
接下來我們需要安裝在react中的支持的jsx,主要依賴babel-loader來編譯jsx

npm i babel-loader --save-dev
并且我們需要改下webpack.config.js的loader

{
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|gif|jpeg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'assets',
              name: '[name].[ext]?[hash]'
            }
          }
        ]
      },
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          presets: ['@babel/env']
        }
      }
    ]
  },
}
在react中我們設(shè)置HMR,我們需要結(jié)合new webpack.HotModuleReplacementPlugin(),并且在devServer中設(shè)置hot為true

module.exports = {
 ...
 plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    new miniCssExtractPlugin({
      filename: 'css/[name].css'
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
      hot: true
  }
}
完整的配置webpack.config.js就已經(jīng)ok了






// webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const miniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'development',
  entry: {
    app: './src/app.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|gif|jpeg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'assets',
              name: '[name].[ext]?[hash]'
            }
          }
        ]
      },
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader',
        options: {
          presets: ['@babel/env']
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    new miniCssExtractPlugin({
      filename: 'css/[name].css'
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    hot: true
  }
};

安裝react、react-dom這兩個核心庫

npm i react react-dom --save-dev
在src目錄下新建一個App.jsx

// App.jsx
import React, {Component} from 'react';
import deepMerge from './utils/index.js';
import '../src/assets/css/app.css';
import image1 from '../src/assets/images/1.png';
import image2 from '../src/assets/images/2.jpg';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      text: 'hello webpack for react',
      name: "Maic",
      age: 18,
      publicName: 'Web技術(shù)學苑',
      imgSource: [image1, image2]
    }
  }
  render() {
    const { text, name, age, publicName, imgSource} = this.state;
    return (<>
      <div className="app">
          <h1>{text}</h1>
          <div>
            <p>{name}</p>,<span>{age}</span>歲
            <p>{publicName}</p>
          </div>
          <div>
            {
              imgSource.map(src => <img src={src} key={src} />)
            }
          </div>
      </div>
    </>)
  }
}
export default App

我們在app.js中引入App.jsx

// app.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';
const appDom = document.getElementById('app');
const root = createRoot(appDom);
root.render(<App />);
我們運行npm run server,瀏覽器打開localhost:8080

好了,用webpack搭建一個自己的react應用就已經(jīng)ok了

總結(jié)
1、react需要的一些插件,@babel/core、@babel/cli、@babel/preset-env、@babel/preset-react、babel-loader

2、設(shè)置.babelrc

3、引入react、react-dom,modules中設(shè)置babel-loader編譯jsx文件

4、本文code-example[3]

參考資料
[1]
從頭開始打造工具鏈: https://medium.com/@JedaiSaboteur/creating-a-react-app-from-scratch-f3c693b84658

[2]
@babel/preset-react: https://www.babeljs.cn/docs/babel-preset-react

[3]
code-example: https://github.com/maicFir/lessonNote/tree/master/webpack/webpack-02







作者:Maic

歡迎關(guān)注微信公眾號 :web技術(shù)學苑