使用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手動單獨下載對應依賴,但有些依賴必須指定版本,否則會有衝突。在專案目錄下建立如下資料夾
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檔案,直接在瀏覽器開啟,結果如下
完成專案搭建