├── .babelrc ├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── mock └── mock-data.js ├── package.json ├── postcss.config.js ├── public ├── favicon.png └── index.html ├── server.js ├── src ├── assets │ ├── demo.wasm │ ├── favicon-144.png │ ├── index.wasm │ ├── loading.gif │ ├── optimized.wasm │ ├── react-logo.jpg │ ├── starSky.mp3 │ └── test.jpg ├── component │ ├── footer │ │ ├── index.js │ │ └── index.less │ ├── loading │ │ ├── index.js │ │ └── index.less │ └── menu │ │ ├── index.js │ │ └── index.less ├── container │ ├── features │ │ ├── index.js │ │ └── index.less │ ├── home │ │ ├── index.js │ │ └── index.less │ ├── notfound │ │ ├── index.js │ │ └── index.less │ ├── routers │ │ ├── index.js │ │ └── index.less │ └── test │ │ ├── container │ │ ├── page1.js │ │ ├── page2.js │ │ └── page3.js │ │ ├── index.js │ │ └── index.less ├── index.js ├── models │ ├── app.js │ └── test.js ├── root │ └── index.js ├── store │ └── index.js ├── styles │ ├── css.css │ └── less.less └── util │ ├── server.js │ └── tools.js ├── webpack.dev.config.js ├── webpack.production.config.js └── 依赖清单.md /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-transform-runtime", 5 | "@babel/plugin-proposal-object-rest-spread", 6 | "@babel/plugin-syntax-dynamic-import", 7 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 8 | "@babel/plugin-proposal-class-properties", 9 | "@babel/plugin-proposal-optional-chaining", 10 | "@babel/plugin-proposal-nullish-coalescing-operator", 11 | "react-loadable/babel", 12 | [ 13 | "import", 14 | { 15 | "libraryName": "antd", 16 | "style": true 17 | } 18 | ] 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "mocha": true 7 | }, 8 | "parser": "@babel/eslint-parser", 9 | "parserOptions": { 10 | "ecmaVersion": 9, 11 | "ecmaFeatures": { 12 | "impliedStrict": true, 13 | "jsx": true 14 | }, 15 | "allowImportExportEverywhere": true, 16 | "sourceType": "module" 17 | }, 18 | "plugins": ["react", "react-hooks", "prettier"], 19 | "rules": { 20 | "semi": "warn", 21 | "no-unused-vars": "off", 22 | "no-cond-assign": "error", 23 | "no-debugger": "warn", 24 | "no-dupe-args": "error", 25 | "no-caller": "error", 26 | "no-unmodified-loop-condition": "error", 27 | "no-with": "error", 28 | "no-catch-shadow": "error", 29 | "react/no-unescaped-entities": "off", 30 | "react-hooks/rules-of-hooks": "error", 31 | "prettier/prettier": "warn", 32 | "no-unused-expressions": "warn" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # mac .DS_Store 2 | .DS_Store 3 | 4 | # Webstorm 5 | .idea 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules 37 | jspm_packages 38 | build 39 | .happypack 40 | yarn.lock 41 | .vscode/* 42 | dll 43 | pnpm-lock.yaml 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # bower 52 | # bower_components 53 | 54 | # access log 55 | access.log 56 | 57 | # backup 58 | backup 59 | 60 | # config.json 61 | config.json 62 | 63 | # build 64 | .build 65 | 66 | # app config 67 | 68 | # tests 69 | mytest/* 70 | 71 | # build 72 | dist/* 73 | !dist/.gitkeep 74 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "14" 4 | - "10" 5 | script: 6 | - yarn build 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 java_luo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React-Luo 2 | 3 | [![Build Status](https://travis-ci.org/javaLuo/react-luo.svg?branch=master)](https://travis-ci.org/javaLuo/react-luo) 4 | [![codebeat badge](https://codebeat.co/badges/eb91ca34-7c1b-424f-be1c-a5d79fd3d269)](https://codebeat.co/projects/github-com-javaluo-react-luo-master) 5 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) ![GitHub last commit](https://img.shields.io/github/last-commit/javaLuo/react-luo.svg?style=popout) 6 | 7 | ## what is this? 8 | 9 | react automatically
10 | 这是一个 React 脚手架,没有使用 create-react-app
11 | 标准的 React+Redux 分层结构
12 | 经过了多个项目的实践,不停的更新和优化出来的。目前自己做项目也在用。 13 | 14 | - PWA、Hooks、代码分割、热替换、HappyPack 多线程构建、ES6+语法 15 | 16 | ## 构建 Start 17 | 18 | ``` 19 | yarn install # 安装依赖模块 20 | 21 | yarn start # 运行开发环境: http://localhost:8888 22 | yarn build # 正式打包,用于生产环境 23 | 24 | yarn dist # 运行正式打包后的最终文件(build目录下的文件): http://localhost:8889 25 | yarn distmac # MAC下运行最终文件:http://localhost:8889 26 | 27 | yarn prettier # 自动格式化src、mock目录下的所有.js/.css/.scss/.less文件 28 | ``` 29 | 30 | ## 更新日志 Update log 31 | 32 | 见Wiki 33 | 34 | ## 目录结构 Structure 35 | 36 | ``` 37 | . 38 | ├── build # 正式打包后,会自动生成该文件夹,其中会包含最终用于生产环境的文件 39 | │   ├── dist # 编译后的资源文件 40 | │   ├── icons # 编译后自动生成的各尺寸favicon图标,有的会用于PWA配置 41 | │   ├── asset-manifets.json # 记录了将会被缓存的资源 42 | │   ├── index.html # 编译后的主页html 43 | │   ├── manifest.json # PWA配置文件,配置了桌面图标,以APP方式启动时的启动页面相关参数 44 | │   └── service-worker.js # PWA核心worker, 用于离线访问,缓存不变的资源文件 45 | ├── mock # mock测试数据 46 | ├── public # 静态文件,index.html等 47 | ├── src                                 # 项目代码目录 48 | │   ├── component                     # 所有的公共类UI组件 49 | │   ├── container                     # 所有的页面级容器组件 50 | | ├── ... 51 | | └── router # 根组件,里面配置了顶级的路由 52 | | ├── models # 模块(包含store数据/reducers/actions) 53 | │ ├── assets # 所有的图片、文件等静态资源 54 | │   ├── styles                         # 所有的样式文件 55 | │   ├── store                          # store数据中心 56 | │ ├── root # 根页 57 | │ ├── store # store数据中心 58 | │ ├── util # 自定义工具 59 | │   ├── index.js                       # 项目入口JS 60 | │   └── index.html                     # 主页html文件,开发环境和生产打包共用 61 | ├── server.js # 用于开发环境的服务部署 62 | ├── webpack.dev.config.js # 用于开发环境的webpack配置 63 | └── webpack.production.config.js # 用于生产环境正式打包的webpack配置 64 | ``` 65 | 66 | ## 预览地址 Demo 67 | 68 | https://isluo.com/work/pwa/ 69 | 70 | ## 参阅资料 71 | 72 | React 英文官网:https://reactjs.org
73 | React 中文文档:https://doc.react-china.org
74 | React GitHub 地址:https://github.com/facebook/react
75 | React 官方更新日志:https://github.com/facebook/react/releases
76 | React 生命周期:https://reactjs.org/docs/react-component.html
77 | mockjs 官网:http://mockjs.com/
78 | Eslint 中文站:http://eslint.cn/
79 | Babel GitHub 地址:https://github.com/babel/babel
80 | -------------------------------------------------------------------------------- /mock/mock-data.js: -------------------------------------------------------------------------------- 1 | /** MOCK 模拟数据拦截ajax请求 **/ 2 | 3 | const Mock = require("mockjs"); 4 | 5 | /** 数据模版 **/ 6 | const ajaxTest = { 7 | status: 200, 8 | "data|1-10": [ 9 | { 10 | "id|+1": 1, 11 | email: "@EMAIL", 12 | }, 13 | ], 14 | }; 15 | 16 | exports.mockApi = (url, params) => { 17 | return Mock.mock(ajaxTest); 18 | }; 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_luo", 3 | "version": "1.0.0", 4 | "description": "react脚手架,最新技术", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node server.js --max_old_space_size=4096", 8 | "build": "webpack --config webpack.production.config.js", 9 | "dist": "set NODE_ENV=production&& node server.js", 10 | "distmac": "export NODE_ENV=production&& node server.js", 11 | "prettier": "prettier --write \"{src,mock}/**/*.{js,css,less}\"", 12 | "cover": "./node_modules/.bin/istanbul cover _mocha", 13 | "coveralls": "npm run cover -- --report lcovonly && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls" 14 | }, 15 | "author": "admin", 16 | "license": "ISC", 17 | "private": true, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/javaLuo/react-luo.git" 21 | }, 22 | "installConfig": { 23 | "pnp": false 24 | }, 25 | "dependencies": { 26 | "@ant-design/icons": "^4.7.0", 27 | "@rematch/core": "^2.2.0", 28 | "antd": "^4.24.2", 29 | "axios": "^1.1.3", 30 | "core-js": "^3.26.1", 31 | "favicons": "6.2.2", 32 | "lodash": "^4.17.21", 33 | "react": "^18.2.0", 34 | "react-dom": "^18.2.0", 35 | "react-loadable": "^5.5.0", 36 | "react-redux": "^8.0.5", 37 | "react-router-dom": "^6.4.3", 38 | "redux": "^4.2.0" 39 | }, 40 | "devDependencies": { 41 | "@babel/core": "^7.20.2", 42 | "@babel/eslint-parser": "^7.19.1", 43 | "@babel/plugin-proposal-class-properties": "^7.18.6", 44 | "@babel/plugin-proposal-decorators": "^7.20.2", 45 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", 46 | "@babel/plugin-proposal-object-rest-spread": "^7.20.2", 47 | "@babel/plugin-proposal-optional-chaining": "^7.18.9", 48 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 49 | "@babel/plugin-transform-runtime": "^7.19.6", 50 | "@babel/preset-env": "^7.20.2", 51 | "@babel/preset-react": "^7.18.6", 52 | "@babel/runtime": "^7.20.1", 53 | "antd-dayjs-webpack-plugin": "^1.0.6", 54 | "autoprefixer": "^10.4.13", 55 | "babel-loader": "^9.1.0", 56 | "babel-plugin-import": "^1.13.5", 57 | "clean-webpack-plugin": "^4.0.0", 58 | "copy-webpack-plugin": "^11.0.0", 59 | "css-loader": "^6.7.2", 60 | "css-minimizer-webpack-plugin": "^4.2.2", 61 | "dayjs": "^1.11.6", 62 | "eslint": "^8.27.0", 63 | "eslint-plugin-prettier": "^4.2.1", 64 | "eslint-plugin-react": "^7.31.10", 65 | "eslint-plugin-react-hooks": "^4.6.0", 66 | "eslint-webpack-plugin": "^3.2.0", 67 | "express": "^4.18.2", 68 | "favicons-webpack-plugin": "^5.0.2", 69 | "happypack": "^5.0.1", 70 | "html-webpack-plugin": "^5.5.0", 71 | "less": "^4.1.3", 72 | "less-loader": "^11.1.0", 73 | "mini-css-extract-plugin": "^2.6.1", 74 | "mockjs": "^1.1.0", 75 | "postcss": "^8.4.19", 76 | "postcss-loader": "^7.0.1", 77 | "prettier": "^2.7.1", 78 | "style-loader": "^3.3.1", 79 | "terser-webpack-plugin": "^5.3.6", 80 | "webpack": "^5.75.0", 81 | "webpack-bundle-analyzer": "^4.7.0", 82 | "webpack-cli": "^4.10.0", 83 | "webpack-dev-middleware": "^5.3.3", 84 | "webpack-hot-middleware": "^2.25.3", 85 | "webpackbar": "^5.0.2", 86 | "workbox-webpack-plugin": "^6.5.4", 87 | "xml-loader": "^1.2.1" 88 | }, 89 | "browserslist": [ 90 | "iOS >= 8", 91 | "last 1 versions", 92 | "> 2%", 93 | "not dead", 94 | "not op_mini all" 95 | ] 96 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /** postcss-loader 解析器所需的配置文件 **/ 2 | module.exports = { 3 | plugins: [ 4 | require('autoprefixer') 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/public/favicon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React 8 | 9 | 10 |
11 | <%= htmlWebpackPlugin.options.registerServiceWorker %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /** 用于开发环境的服务启动 **/ 2 | const path = require("path"); // 获取绝对路径有用 3 | const express = require("express"); // express服务器端框架 4 | const env = process.env.NODE_ENV; // 模式(dev开发环境,production生产环境) 5 | const webpack = require("webpack"); // webpack核心 6 | const webpackDevMiddleware = require("webpack-dev-middleware"); // webpack服务器 7 | const webpackHotMiddleware = require("webpack-hot-middleware"); // HMR热更新中间件 8 | const webpackConfig = require("./webpack.dev.config.js"); // webpack开发环境的配置文件 9 | 10 | const mock = require("./mock/mock-data"); // mock模拟数据,模拟后台业务 11 | 12 | const app = express(); // 实例化express服务 13 | const DIST_DIR = webpackConfig.output.path; // webpack配置中设置的文件输出路径,所有文件存放在内存中 14 | let PORT = 8888; // 服务启动端口号 15 | 16 | app.use(express.urlencoded({ extended: false })); 17 | app.use(express.json()); 18 | 19 | /** 监听POST请求,返回MOCK模拟数据 **/ 20 | app.post(/\/api.*/, (req, res, next) => { 21 | const result = mock.mockApi({ url: req.originalUrl, body: req.body }); 22 | res.send(result); 23 | }); 24 | app.get(/\/api.*/, (req, res, next) => { 25 | const result = mock.mockApi({ url: req.originalUrl, body: req.body }); 26 | res.send(result); 27 | }); 28 | 29 | if (env === "production") { 30 | // 如果是生产环境,则运行build文件夹中的代码 31 | PORT = 8889; 32 | app.use(express.static("build")); 33 | app.get("*", (req, res) => { 34 | res.sendFile(path.join(__dirname, "build", "index.html")); 35 | }); 36 | } else { 37 | const compiler = webpack(webpackConfig); // 实例化webpack 38 | app.use(express.static("dll")); 39 | app.use( 40 | webpackDevMiddleware(compiler, { 41 | publicPath: webpackConfig.output.publicPath, // 对应webpack配置中的publicPath 42 | }), 43 | ); 44 | 45 | app.use(webpackHotMiddleware(compiler)); // 挂载HMR热更新中间件 46 | // 所有请求都返回index.html 47 | app.get("*", (req, res, next) => { 48 | const filename = path.join(DIST_DIR, "index.html"); 49 | 50 | // 由于index.html是由html-webpack-plugin生成到内存中的,所以使用下面的方式获取 51 | compiler.outputFileSystem.readFile(filename, (err, result) => { 52 | if (err) { 53 | return next(err); 54 | } 55 | res.set("content-type", "text/html"); 56 | res.send(result); 57 | res.end(); 58 | }); 59 | }); 60 | } 61 | 62 | /** 启动服务 **/ 63 | app.listen(PORT, () => { 64 | console.log("本地服务启动地址: http://localhost:%s", PORT); 65 | }); 66 | -------------------------------------------------------------------------------- /src/assets/demo.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/demo.wasm -------------------------------------------------------------------------------- /src/assets/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/favicon-144.png -------------------------------------------------------------------------------- /src/assets/index.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/index.wasm -------------------------------------------------------------------------------- /src/assets/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/loading.gif -------------------------------------------------------------------------------- /src/assets/optimized.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/optimized.wasm -------------------------------------------------------------------------------- /src/assets/react-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/react-logo.jpg -------------------------------------------------------------------------------- /src/assets/starSky.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/starSky.mp3 -------------------------------------------------------------------------------- /src/assets/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaLuo/react-luo/a551c868257830db93ae04908984407611475033/src/assets/test.jpg -------------------------------------------------------------------------------- /src/component/footer/index.js: -------------------------------------------------------------------------------- 1 | /** Footer 页面底部 **/ 2 | import React from "react"; 3 | import "./index.less"; 4 | 5 | export default function Footer() { 6 | return ( 7 |
8 | © 2018-{new Date().getFullYear()}{" "} 9 | 14 | blog.isluo.com 15 | 16 | , Inc. 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/component/footer/index.less: -------------------------------------------------------------------------------- 1 | .footer { 2 | text-align: center; 3 | padding: 5px 0; 4 | a:hover { 5 | text-decoration: underline; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/component/loading/index.js: -------------------------------------------------------------------------------- 1 | /** Loading组件 用于按需加载时过渡显示等 **/ 2 | import React from "react"; 3 | import "./index.less"; 4 | import ImgLoading from "../../assets/loading.gif"; 5 | export default function LoadingComponent(props) { 6 | function makeType(p) { 7 | let msg; 8 | if (p.error) { 9 | msg = "加载出错,请刷新页面"; 10 | } else if (p.timedOut) { 11 | msg = "加载超时"; 12 | } else if (p.pastDelay) { 13 | msg = "加载中…"; 14 | } 15 | return msg; 16 | } 17 | 18 | return ( 19 |
20 | 21 |
{makeType(props)}
22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/component/loading/index.less: -------------------------------------------------------------------------------- 1 | .loading { 2 | text-align: center; 3 | padding: 50px; 4 | font-size: 14px; 5 | position: relative; 6 | margin: 0 auto; 7 | img { 8 | margin-bottom: 12px; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/component/menu/index.js: -------------------------------------------------------------------------------- 1 | /** 导航 **/ 2 | 3 | import React from "react"; 4 | import { Link } from "react-router-dom"; 5 | import { useNavigate } from "react-router-dom"; 6 | import "./index.less"; 7 | 8 | export default function Menu() { 9 | const navigate = useNavigate(); 10 | 11 | function goToTest() { 12 | navigate("/test?a=123&b=abc", { state: { c: 456, d: "ABC" } }); 13 | } 14 | 15 | return ( 16 |
17 | 首页|构建与特性| 18 | 19 | 测试:Link跳转 20 | 21 | | 22 | goToTest()} 25 | to={{ 26 | pathname: "/test", 27 | search: "?a=123&b=abc", 28 | }} 29 | state={{ c: 456, d: "ABC" }} 30 | > 31 | 测试:api跳转 32 | 33 | | 34 | 39 | GitHub 40 | 41 |
42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /src/component/menu/index.less: -------------------------------------------------------------------------------- 1 | .menu { 2 | margin-top: 10px; 3 | color: #888; 4 | text-align: center; 5 | .active { 6 | color: #67daf9; 7 | } 8 | a, 9 | .link { 10 | padding: 0 5px; 11 | color: #0066cc; 12 | text-decoration: none; 13 | cursor: pointer; 14 | &:hover { 15 | text-decoration: underline; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/container/features/index.js: -------------------------------------------------------------------------------- 1 | /** 构建与特性页 **/ 2 | 3 | /** 所需的各种插件 **/ 4 | import React from "react"; 5 | 6 | /** 所需的所有资源 **/ 7 | import "./index.less"; 8 | 9 | export default function FeaturesPageContainer(props) { 10 | return ( 11 |
12 |

构建与特性

13 |
14 |
15 |

安装依赖文件

16 |

npm install

17 |
18 |
19 |

启动开发环境

20 |

npm run start

21 |
代码打包编译,默认监听8888端口
22 |
访问http://localhost:8888 即可查看
23 |
24 |
25 |

正式打包

26 |

npm run build

27 |
会将最终代码打包至/build文件夹中
28 |
29 |
30 |

运行生产环境的代码

31 |

npm run dist (windows系统)

32 |

npm run distmac (Mac/Linux系统)

33 |
运行build文件夹下生成好的最终代码
34 |
35 |
36 |

代码自动格式化

37 |

npm run prettier

38 |
自动美化所有js/css/less等文件
39 |
40 |
41 |

HMR局部热更新

42 |
43 | 使用webpack-dev-middleware 和 webpack-hot-middleware设置了热更新 44 |
45 |
46 |
47 |

代码分割

48 |
react-loadable实现的代码分割
49 |
src/container/root/index.js中能查看例子
50 |
51 |
52 |

webpack5.x

53 |
使用了最新版本的webpack,编译速度更快
54 |
55 |
56 |
57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/container/features/index.less: -------------------------------------------------------------------------------- 1 | .page-features { 2 | width: 100%; 3 | max-width: 1200px; 4 | margin: 0 auto; 5 | padding: 40px; 6 | letter-spacing: 1px; 7 | .box { 8 | margin-top: 40px; 9 | .list { 10 | margin-bottom: 20px; 11 | p { 12 | font-size: 14px; 13 | padding: 5px 10px; 14 | margin: 10px 0; 15 | background-color: #eeeeff; 16 | } 17 | div { 18 | color: #888; 19 | font-size: 12px; 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/container/home/index.js: -------------------------------------------------------------------------------- 1 | /** 主页 **/ 2 | 3 | /** 所需的各种插件 **/ 4 | import React from "react"; 5 | import { useStore } from "react-redux"; 6 | 7 | /** 所需的各种资源 **/ 8 | import "./index.less"; 9 | import ImgLogo from "../../assets/react-logo.jpg"; 10 | 11 | export default function HomePageContainer(props) { 12 | const store = useStore(); 13 | console.log("store:", store); 14 | console.log("what props:", props); 15 | return ( 16 |
17 |
18 | 19 |
React-Luo
20 |
21 | react17、redux4、router6、webpack5、eslint、babel7、antd4 22 |
23 |
24 |
25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/container/home/index.less: -------------------------------------------------------------------------------- 1 | .page-home { 2 | padding: 100px 0 0 0; 3 | .box { 4 | margin: 0 auto; 5 | text-align: center; 6 | .title { 7 | font-size: 24px; 8 | } 9 | .info { 10 | margin-top: 10px; 11 | color: #888; 12 | } 13 | .link { 14 | margin-top: 40px; 15 | font-size: 12px; 16 | color: #888; 17 | a { 18 | color: #888; 19 | text-decoration: none; 20 | &:hover { 21 | text-decoration: underline; 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/container/notfound/index.js: -------------------------------------------------------------------------------- 1 | /** 404 NotFound **/ 2 | 3 | /** 所需的各种插件 **/ 4 | import React from "react"; 5 | 6 | /** 所需的所有资源 **/ 7 | import "./index.less"; 8 | 9 | export default function NotFoundPageContainer() { 10 | return ( 11 |
12 |
404 not found
13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/container/notfound/index.less: -------------------------------------------------------------------------------- 1 | .page-notfound { 2 | height: calc(100vh - 62px); 3 | .box { 4 | position: absolute; 5 | top: 40%; 6 | left: 50%; 7 | transform: translate(-50%, -50%); 8 | font-size: 16px; 9 | color: #888; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/container/routers/index.js: -------------------------------------------------------------------------------- 1 | /** 路由页 - 真正意义上的根组件,已挂载到redux上,可获取store中的内容 **/ 2 | 3 | /** 所需的各种插件 **/ 4 | import React, { useEffect } from "react"; 5 | 6 | // import { Router, Route, Switch, Redirect } from "react-router-dom"; 7 | import { 8 | HashRouter as Router, 9 | Routes, 10 | Route, 11 | Navigate, 12 | } from "react-router-dom"; 13 | 14 | // antd的多语言 15 | import { ConfigProvider } from "antd"; 16 | import zhCN from "antd/lib/locale-provider/zh_CN"; 17 | 18 | // import { createBrowserHistory as createHistory } from "history/"; // URL模式的history 19 | // import { createHashHistory as createHistory } from "history"; // 锚点模式的history 20 | 21 | import Loadable from "react-loadable"; // 用于代码分割时动态加载模块 22 | 23 | /** 普通组件 **/ 24 | import Menu from "../../component/menu"; 25 | import Footer from "../../component/footer"; 26 | import Loading from "../../component/loading"; // loading动画,用于动态加载模块进行中时显示 27 | 28 | import "./index.less"; 29 | 30 | /** 下面是代码分割异步加载的方式引入各页面 webpackChunkName设置生成后的js名字 **/ 31 | const Home = Loadable({ 32 | loader: () => import(/* webpackChunkName:'home' */ "../home"), 33 | loading: Loading, // 自定义的Loading动画组件 34 | timeout: 10000, // 可以设置一个超时时间(s)来应对网络慢的情况(在Loading动画组件中可以配置error信息) 35 | }); 36 | const Test = Loadable({ 37 | loader: () => import(/* webpackChunkName:'test' */ "../test"), 38 | loading: Loading, 39 | }); 40 | const Page1 = Loadable({ 41 | loader: () => 42 | import(/* webpackChunkName:'testclass' */ "../test/container/page1"), 43 | loading: Loading, 44 | }); 45 | const Page2 = Loadable({ 46 | loader: () => 47 | import(/* webpackChunkName:'testclass' */ "../test/container/page2"), 48 | loading: Loading, 49 | }); 50 | const Page3 = Loadable({ 51 | loader: () => 52 | import(/* webpackChunkName:'testclass' */ "../test/container/page3"), 53 | loading: Loading, 54 | }); 55 | const Features = Loadable({ 56 | loader: () => import(/* webpackChunkName:'features' */ "../features"), 57 | loading: Loading, 58 | }); 59 | const NotFound = Loadable({ 60 | loader: () => import(/* webpackChunkName:'notfound' */ "../notfound"), 61 | loading: Loading, 62 | }); 63 | 64 | // const history = createHistory(); // 实例化history对象 65 | 66 | /** 组件 **/ 67 | export default function RootRouterContainer(props) { 68 | // 在组件加载完毕后触发 69 | useEffect(() => { 70 | // 可以手动在此预加载指定的模块: 71 | // Features.preload(); // 预加载Features页面 72 | // Test.preload(); // 预加载Test页面 73 | // 也可以直接预加载所有的异步模块 74 | // Loadable.preloadAll(); 75 | }, []); 76 | 77 | /** 简单权限控制 路由守卫 **/ 78 | function onEnter(Component) { 79 | // 例子:如果没有登录,直接跳转至login页 80 | // if (sessionStorage.getItem('userInfo')) { 81 | // return Component; 82 | // } else { 83 | // return ; 84 | // } 85 | return Component; 86 | } 87 | 88 | return ( 89 | 90 | <> 91 | 92 |
93 | 94 | } /> 95 | )} /> 96 | )} /> 97 | )}> 98 | )} /> 99 | )} /> 100 | )} /> 101 | 102 | } /> 103 | 104 | 105 |
106 |
107 |