目录结构
|
|
|
|
|
|
|
| |
|
| |
| |
|
|
|
|
|
|
|
| |
|
| |
|
| |
| |
|
|
|
|
步骤
- 安装依赖包;
- 配置webpack;
- .babelrc
- dev-server
- html-webpack-plugin
- loader
- plugins
- 入口文件;
- router
- redux;
安装依赖 package.json
{
"name": "sfg",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack serve -c ./build/webpack.dev.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.16",
"@babel/preset-env": "^7.13.15",
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@babel/runtime": "^7.13.17",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"copy-webpack-plugin": "^8.1.1",
"cross-env": "^7.0.3",
"css-loader": "^5.2.4",
"html-webpack-plugin": "^5.3.1",
"mddir": "^1.1.1",
"postcss-loader": "^5.2.0",
"postcss-px2vw": "^0.0.1",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.35.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
},
"dependencies": {
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.13.15",
"@reduxjs/toolkit": "^1.5.1",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.7",
"@types/redux": "^3.6.0",
"core-js": "3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"sass": "^1.32.11"
}
}
Webpack 相关的
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns" : "usage",
"corejs" : "3",
"targets": "> 0.25%, not dead",
"modules" : "amd"
}
],
[
"@babel/preset-typescript",{
"isTSX": true,
"allExtensions" : true
}
],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-syntax-dynamic-import"
]
}
Webpack.base.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'),
{CleanWebpackPlugin} = require('clean-webpack-plugin'),
CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: {
index: path.join(__dirname,'../src','index.ts'),
},
output: {
path: path.join(__dirname,'..','dist'),
filename: '[name].[contenthash].js'
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
"style-loader",
"css-loader",
"sass-loader",
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname,'../src','index.html'),
inject: 'body'
}),
],
resolve: {
alias: {
"@" : path.join(__dirname,'../src'),
"@views": path.join(__dirname,'../src/','views'),
"@components": path.join(__dirname,'../src/','components'),
},
extensions: [".tsx",".ts",".js"],
}
}
Webpack.dev.js
const path = require('path');
const { merge } = require('webpack-merge');
const base = require('./webpack.base.js');
module.exports = merge(base,{
mode: "development",
devServer: {
contentBase: [
path.join(__dirname,'../dist'),
path.join(__dirname,'../assets'),
],
contentBasePublicPath: [
'/','/assets'
],
port: 9000,
hot: true,
index: 'index.html'
}
})
src/index.ts
import './scss/index.scss';
import React from 'react';
import {render} from 'react-dom';
import Home from './Home.tsx';
render(<Home/>, document.querySelector('#app'));
src/Home.tsx
import React , {Component, Suspense, lazy} from 'react';
import {RouterList,} from '@/routes/index';
import store, {add} from '@/stores/index.ts';
import {Provider, connect} from 'react-redux';
import {
HashRouter as Router,
Switch,
Route,
} from 'react-router-dom';
class Home extends Component{
render(){
const renderList = function(list){
return list.map(route=>{
return <Route exact key={route.path} path={route.path} component={route.component}></Route>
})
}
return (
<Provider store={store}>
<Router>
<Suspense fallback={<div>...</div>}>
<Switch>
{
renderList(RouterList)
}
</Switch>
</Suspense>
</Router>
</Provider>
)
}
}
export default Home;
src/router/index.ts
import React, {lazy} from 'react';
let Index = lazy(()=>import('@views/Index'));
let User = lazy(()=>import('@views/User'));
export const RouterList = [
{
path: "/",
name: "首页",
exact: true,
component: Index,
},
{
path: "/user",
name: "用户",
exact: true,
component: User,
},
]
src/views/index.ts
import React, {Component,} from 'react';
import {useSelector,useDispatch,} from 'react-redux'
import {add} from '@/stores/index'
export default function(props){
const dis = useDispatch();
const clickHandle = function(){
dis({
type: 'counter/add',
payload: 15
});
}
const counter = useSelector(state => state.CounterSlice.counter);
console.log(counter);
return <div onClick={clickHandle}>---{counter.value}---</div>
}
src/views/User.tsx
import React ,{ Component} from 'react';
import {connect} from 'react-redux';
import {add,CounterStore} from '@/stores/index';
class User extends Component{
componentDidMount(){
console.log(this.props);
}
render(){
return <div onClick={()=>this.props.add(11)}>{this.props.counter.value}</div>
}
}
export default connect(CounterStore,{add})(User);
src/stores/CounterSlice.ts
import {createSlice} from '@reduxjs/toolkit';
const CounterSlice = createSlice({
name: "counter",
initialState: {
counter: {
value: 11,
}
},
reducers: {
add: (state,{payload}) => {
state.counter.value += payload;
return;
}
}
})
export default CounterSlice;
src/stores/index.ts
import {configureStore, createStore} from '@reduxjs/toolkit';
import CounterSlice from './CounterSlice';
export const CounterStore = state => state.CounterSlice;
export const {add} = CounterSlice.actions;
export default configureStore({
reducer: {
CounterSlice : CounterSlice.reducer,
}
});