天天看點

使用webpack搭建react+antd項目

目前網絡上關于react和antd的教程有很多,在建構項目階段大多用create-react-app,dva等腳手架工具進行搭建,使用工具固然友善,卻總感覺沒能真正完全掌握這門技術,于是自己嘗試從頭搭建了一個項目

1.環境

    本機使用v8.9.4版本的node,開發工具為Visual Studio Code

2.初始化項目

在項目目錄下執行指令 npm init 初始化項目,在生成的 package.json 檔案中添加以下依賴并執行 npm install 

"dependencies": {
    "antd": "^3.10.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.2",
    "babel-plugin-import": "^1.9.1",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^1.0.0",
    "eslint": "^5.7.0",
    "eslint-loader": "^2.1.1",
    "eslint-plugin-react": "^7.11.1",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.5.2",
    "react-dev-utils": "^6.0.5",
    "react-dom": "^16.5.2",
    "react-router-dom": "^4.3.1",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.9"
  }
           

    當然也可以使用npm install手動單獨下載下傳對應依賴,但有些依賴必須指定版本,否則會有沖突。在項目目錄下建立如下檔案夾

使用webpack搭建react+antd項目

src用于放置react元件,public用于放置靜态檔案,dist放置編譯目标檔案,config用于放置配置檔案

3.配置webpack

在config中建立webpack配置檔案,任意命名,我這裡命名為webpack.config.js。建立用于控制路徑的配置檔案,我這裡命名為paths.js

'use strict';
const path = require('path');
const fs = require('fs');

const appDirectory = fs.realpathSync(process.cwd());
const resolveAppPath = relativePath => path.resolve(appDirectory, relativePath);

module.exports = {
    mainJs:resolveAppPath('src/main.js'),
    html:resolveAppPath('public/index.html'),
    buildPath:resolveAppPath('dist'),
};
           

paths.js檔案用于配置在編譯時可能用到的一些路徑,并将其轉化為絕對路徑,這裡導入了三個路徑

1.mainJs:入口檔案,可以了解為我們的靜态頁面在未編譯時所引入的唯一js檔案,這也是react官方推薦的模式

2.html:靜态頁面路徑

3.biildPath:編譯完成後的檔案應該放置的目錄

const path = require('path');
const paths = require('./paths');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: paths.mainJs,
    output: {
        filename: 'bundle-[hash].js',
        path: paths.buildPath
        },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },{
                 test: /\.css$/, 
                 use: ['style-loader', 'css-loader'] 
            },{ 
                test: /\.(png|jpg|jpeg|gif)$/, 
                use: 'url-loader' 
            },
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: paths.html,
            inject: true
        })
    ]
  };
           

entry選項用于指定入口檔案,,可以了解為我們的靜态頁面在未編譯時所引入的唯一js檔案

output選項用于指定編譯結果,filename設定編譯完成的檔案名稱,使用[hash]将編譯完成的js檔案加上哈希碼,防止浏覽器緩存,path指定js檔案放置目錄

需要注意的是除了使用babel-loader對js檔案的文法進行轉換之外,還要用style-loader和css-loader對css檔案進行轉換,否則在使用antd的樣式時會報錯,使用HtmlWebpackPlugin在編譯時往html檔案中插入編譯後的js檔案

對于babel的配置主要有兩種方式,一種是在項目根目錄下建立.babelrc檔案

{
    "presets": [
      "es2015",
      "react"
    ],
    "plugins": ["transform-class-properties",["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }]]
  }
           

加入transform-class-properties插件可以使用屬性初始化器文法,不用在構造函數中定義屬性,同時配置babel-plugin-import,實作antd的按需引入

4.測試

在src目錄下建立page目錄,建立index.js檔案,編寫一個測試元件,這裡用antd官方文檔上的示範代碼

import React from 'react';
import { Menu, Icon, Switch } from 'antd';

const { SubMenu } = Menu;

class Sider extends React.Component {
  state = {
    mode: 'inline',
    theme: 'light',
  }

  changeMode = (value) => {
    this.setState({
      mode: value ? 'vertical' : 'inline',
    });
  }

  changeTheme = (value) => {
    this.setState({
      theme: value ? 'dark' : 'light',
    });
  }

  render() {
    return (
      <div>
        <Switch onChange={this.changeMode} /> Change Mode
        <span className="ant-divider" style={{ margin: '0 1em' }} />
        <Switch onChange={this.changeTheme} /> Change Theme
        <br />
        <br />
        <Menu
          style={{ width: 256 }}
          defaultSelectedKeys={['1']}
          defaultOpenKeys={['sub1']}
          mode={this.state.mode}
          theme={this.state.theme}
        >
          <Menu.Item key="1">
            <Icon type="mail" />
            Navigation One
          </Menu.Item>
          <Menu.Item key="2">
            <Icon type="calendar" />
            Navigation Two
          </Menu.Item>
          <SubMenu key="sub1" title={<span><Icon type="appstore" /><span>Navigation Three</span></span>}>
            <Menu.Item key="3">Option 3</Menu.Item>
            <Menu.Item key="4">Option 4</Menu.Item>
            <SubMenu key="sub1-2" title="Submenu">
              <Menu.Item key="5">Option 5</Menu.Item>
              <Menu.Item key="6">Option 6</Menu.Item>
            </SubMenu>
          </SubMenu>
          <SubMenu key="sub2" title={<span><Icon type="setting" /><span>Navigation Four</span></span>}>
            <Menu.Item key="7">Option 7</Menu.Item>
            <Menu.Item key="8">Option 8</Menu.Item>
            <Menu.Item key="9">Option 9</Menu.Item>
            <Menu.Item key="10">Option 10</Menu.Item>
          </SubMenu>
        </Menu>
      </div>
    );
  }
}

export default Sider;
           

建立router檔案夾,在其中建立router.js檔案,編寫路由

import React from 'react';
import {HashRouter,Route,Switch,Link} from 'react-router-dom'

import Sider from '../page/index'

export default class AppRouter extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <HashRouter>
                <div id="wrapper">
                    <Route path="/" component={Sider}/>
                </div>
            </HashRouter>
        )
    }
}
           

在入口檔案main.js中引入

import React, { Component } from 'react';
import { render } from 'react-dom';
import AppRouter from './router/router'

render(
    <AppRouter/>,
    document.getElementById('root')
);
           

指令行執行webpack --config ./config/webpack.config.js(在package.json檔案中配置 "build":"webpack --config ./config/webpack.config.js" 可直接使用npm run build),在dist目錄下會出現編譯後的html檔案和js檔案,直接在浏覽器打開,結果如下

使用webpack搭建react+antd項目

完成項目搭建

繼續閱讀