├── .gitignore ├── README.md ├── babel.config.js ├── build ├── webpack.base.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── package.json ├── public ├── favicon.ico └── index.html └── src ├── App.js ├── App.less ├── App.scss ├── GlobalModel.js ├── components └── .gitkeep ├── index.js ├── pages ├── display │ ├── index.js │ ├── model │ │ └── index.js │ └── service │ │ └── index.js ├── exception │ └── index.js ├── home │ └── index.js └── settings │ └── index.js └── utils └── request.js /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # production 5 | /dist 6 | 7 | # misc 8 | .DS_Store 9 | .vscode 10 | .ideal 11 | 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | yarn.lock 16 | package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-quickstart-template 2 | React 脚手架模板 3 | 4 | ## fe-start-kit 5 | 前端脚手架工具[fe-start-kit](https://github.com/lazyperson/fe-start-kit) 6 | 7 | ## 安装插件 8 | 9 | `npm install` 10 | 11 | ## 运行项目 12 | 13 | `npm run start` 14 | 15 | 打开浏览器,输入:`localhost:8000` 查看项目运行效果 16 | 17 | 18 | ## 项目打包 19 | 20 | `npm run build` 21 | 22 | 新增 `dist` 目录,里面是打包好的项目代码 23 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (api) => { 2 | api.cache(true); 3 | 4 | return { 5 | presets: [ 6 | "@babel/preset-env", 7 | "@babel/preset-react" 8 | ], 9 | plugins: [ 10 | [ 11 | "@babel/plugin-proposal-decorators", 12 | { 13 | "legacy": true 14 | } 15 | ], 16 | [ 17 | "import", 18 | { 19 | "libraryName": "antd", 20 | "style": true 21 | } 22 | ], 23 | [ 24 | "@babel/plugin-transform-runtime", 25 | { 26 | "corejs": 2 27 | } 28 | ], 29 | [ 30 | "@babel/plugin-proposal-class-properties", 31 | { 32 | "loose": true 33 | } 34 | ], 35 | "@babel/plugin-syntax-dynamic-import", 36 | // "@babel/plugin-syntax-import-meta", 37 | // 可以用 const ex = "before 38 | // after"; 这种方式编写字符串 39 | // "@babel/plugin-proposal-json-strings", 40 | // 可以使用 generate 语法 41 | // "@babel/plugin-proposal-function-sent", 42 | // 可以使用 export * 这种命名空间的方式导出模块 43 | "@babel/plugin-proposal-export-namespace-from", 44 | // 可以使用数字分离器书写数字 45 | // "@babel/plugin-proposal-numeric-separator" 46 | // 可以使用异常抛出表达式, 47 | "@babel/plugin-proposal-throw-expressions", 48 | // 默认导出 49 | "@babel/plugin-proposal-export-default-from", 50 | // 可以使用逻辑赋值运算符 51 | "@babel/plugin-proposal-logical-assignment-operators", 52 | // 可以使用可选链的方式访问深层嵌套的属性或者函数 ?. 53 | "@babel/plugin-proposal-optional-chaining", 54 | // 可以使用管道运算符 |> 55 | [ 56 | "@babel/plugin-proposal-pipeline-operator", 57 | { 58 | "proposal": "minimal" 59 | } 60 | ], 61 | // 可以使用空值合并语法 ?? 62 | "@babel/plugin-proposal-nullish-coalescing-operator", 63 | // 可以使用 do 表达式(可以认为是三元运算符的复杂版本) 64 | "@babel/plugin-proposal-do-expressions", 65 | // 可以使用功能绑定语法 obj::func 66 | "@babel/plugin-proposal-function-bind" 67 | ] 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /build/webpack.base.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HTMLWebpackPlugin = require('html-webpack-plugin'); 3 | const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | const autoprefixer = require('autoprefixer'); 6 | 7 | const appSrc = path.resolve(__dirname, '../src'); 8 | const appDist = path.resolve(__dirname, '../dist'); 9 | const appPublic = path.resolve(__dirname, '../public'); 10 | const appIndex = path.resolve(appSrc, 'index.js'); 11 | const appHtml = path.resolve(appPublic, 'index.html'); 12 | 13 | module.exports = { 14 | entry: { 15 | main: [appIndex], 16 | common: ['react', 'react-dom', 'react-router-dom', 'mobx'] 17 | }, 18 | output: { 19 | filename: 'public/js/[name].[hash:8].js', 20 | path: appDist, 21 | publicPath: '/' 22 | }, 23 | plugins: [ 24 | // 自动在出口目录生成 html 并自动引入 js 文件 25 | new HTMLWebpackPlugin({ 26 | template: appHtml, 27 | filename: 'index.html' 28 | }), 29 | // 在命令行展示更清晰地提示信息 30 | new FriendlyErrorsWebpackPlugin() 31 | ], 32 | module: { 33 | rules: [ 34 | // 解析 js 35 | { 36 | test: /\.(js|jsx)$/, 37 | loader: 'babel-loader?cacheDirectory', 38 | include: [ appSrc ], 39 | exclude: /node_modules/ 40 | }, 41 | // 解析样式 42 | { 43 | test: /\.(css|less)$/, 44 | exclude: /node_modules/, 45 | use: [ 46 | { 47 | // 使用 MiniCssExtractPlugin.loader 代替 style-loader 48 | loader: MiniCssExtractPlugin.loader 49 | }, 50 | { 51 | loader: 'css-loader', 52 | options: { 53 | sourceMap: true, 54 | modules: true, 55 | localIdentName: '[local].[hash:8]' 56 | } 57 | }, 58 | { 59 | loader: 'postcss-loader', 60 | options: { 61 | plugins: () => [autoprefixer()] 62 | } 63 | }, 64 | { 65 | loader: 'less-loader', 66 | options: { 67 | javascriptEnabled: true 68 | } 69 | } 70 | ] 71 | }, 72 | { 73 | test: /\.(css|less)$/, 74 | include: /node_modules/, 75 | use: [ 76 | { 77 | loader: MiniCssExtractPlugin.loader 78 | }, 79 | { 80 | loader: 'css-loader', 81 | options: {} 82 | }, 83 | { 84 | loader: 'less-loader', 85 | options: { 86 | javascriptEnabled: true 87 | } 88 | } 89 | ] 90 | }, 91 | { 92 | test: /\.scss$/, 93 | exclude: /node_modules/, 94 | use: [ 95 | { 96 | loader: MiniCssExtractPlugin.loader 97 | }, 98 | { 99 | loader: 'css-loader', 100 | options: { 101 | sourceMap: true, 102 | modules: true, 103 | localIdentName: '[local].[hash:8]' 104 | } 105 | }, 106 | { 107 | loader: 'postcss-loader', 108 | options: { 109 | plugins: () => [autoprefixer()] 110 | } 111 | }, 112 | { 113 | loader: 'sass-loader', 114 | options: { 115 | javascriptEnabled: true 116 | } 117 | } 118 | ] 119 | }, 120 | // 解析图片资源 121 | { 122 | test: /\.(png|svg|jpg|gif)$/, 123 | use: [ 124 | 'file-loader' 125 | ] 126 | }, 127 | // 解析 字体 128 | { 129 | test: /\.(woff|woff2|eot|ttf|otf)$/, 130 | use: [ 131 | 'file-loader' 132 | ] 133 | } 134 | ] 135 | }, 136 | resolve: { 137 | // 设置别名 138 | alias: { 139 | '@src': appSrc, 140 | '@utils': path.resolve(__dirname, '../src/utils'), 141 | '@pages': path.resolve(__dirname, '../src/pages'), 142 | '@components': path.resolve(__dirname, '../src/components') 143 | }, 144 | // 设置模块查找范围 145 | modules: [path.resolve(__dirname, '../node_modules')] 146 | } 147 | } -------------------------------------------------------------------------------- /build/webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const merge = require('webpack-merge'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | const base = require('./webpack.base'); 6 | 7 | const appPublic = path.resolve(__dirname, '../public'); 8 | 9 | const config = merge(base, { 10 | mode: 'development', 11 | devtool: 'inline-source-map', 12 | devServer: { 13 | // 作为服务器发布的目录 14 | contentBase: appPublic, 15 | // 热加载 16 | hot: true, 17 | // host 地址 18 | host: 'localhost', 19 | // 端口号 20 | port: 8000, 21 | historyApiFallback: true, 22 | // 是否在浏览器蒙层展示错误信息 23 | overlay: true, 24 | inline: true, 25 | // 展示的统计信息 26 | stats: 'errors-only', 27 | // 配置代理 28 | proxy: { 29 | '/api': { 30 | changeOrigin: true, 31 | target: 'https://easy-mock.com/mock/5c2dc9665cfaa5209116fa40/example', 32 | pathRewrite: { 33 | '^/api/': '/' 34 | } 35 | } 36 | } 37 | }, 38 | plugins: [ 39 | // 热加载插件 40 | new webpack.HotModuleReplacementPlugin(), 41 | // 提取 css 文件 42 | new MiniCssExtractPlugin({ 43 | filename: 'public/styles/[name].css', 44 | chunkFilename: 'public/styles/[name].chunk.css' 45 | }) 46 | ] 47 | }); 48 | 49 | module.exports = config; -------------------------------------------------------------------------------- /build/webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | const TerserPlugin = require('terser-webpack-plugin'); 4 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 6 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 7 | const merge = require('webpack-merge'); 8 | const base = require('./webpack.base'); 9 | 10 | const config = merge(base, { 11 | mode: 'production', 12 | devtool: 'hidden-source-map', 13 | plugins: [ 14 | // 提取 css 文件 15 | new MiniCssExtractPlugin({ 16 | filename: 'public/styles/[name].[contenthash:8].css', 17 | chunkFilename: 'public/styles/[name].[contenthash:8].chunk.css' 18 | }), 19 | // 区分环境 20 | new webpack.DefinePlugin({ 21 | // 定义 NODE_ENV 环境变量为 production 22 | 'process.env': { 23 | NODE_ENV: JSON.stringify('production') 24 | } 25 | }), 26 | // 清理 dist 文件,2.0.0 版本之后不需要设置参数就可以自动清除打包生成的目录 27 | new CleanWebpackPlugin() 28 | ], 29 | optimization: { 30 | // 打包压缩js/css文件 31 | minimizer: [ 32 | new TerserPlugin(), 33 | // new UglifyJsPlugin({ 34 | // uglifyOptions: { 35 | // compress: {} 36 | // // 在UglifyJs删除没有用到的代码时不输出警告 37 | // warnings: false, 38 | // // 删除所有的 `console` 语句,可以兼容ie浏览器 39 | // drop_console: true, 40 | // // 内嵌定义了但是只用到一次的变量 41 | // collapse_vars: true, 42 | // // 提取出出现多次但是没有定义成变量去引用的静态值 43 | // reduce_vars: true, 44 | // }, 45 | // output: { 46 | // // 最紧凑的输出 47 | // beautify: false, 48 | // // 删除所有的注释 49 | // comments: false, 50 | // } 51 | // } 52 | // }), 53 | // 压缩 CSS 代码 54 | new OptimizeCSSAssetsPlugin({ 55 | safe: true, 56 | discardComments: { 57 | removeAll: true // 移除注释 58 | } 59 | }) 60 | ], 61 | // 拆分公共模块 62 | splitChunks: { 63 | cacheGroups: { 64 | styles: { 65 | name: 'styles', 66 | test: /\.(css|less)/, 67 | chunks: 'all', 68 | enforce: true, 69 | // 表示是否使用已有的 chunk 70 | reuseExistingChunk: true 71 | }, 72 | commons: { 73 | name: 'commons', 74 | chunks: 'initial', 75 | minChunks: 2, 76 | reuseExistingChunk: true 77 | }, 78 | vendors: { 79 | name: 'vendors', 80 | test: /[\\/]node_modules[\\/]/, 81 | priority: -10, 82 | reuseExistingChunk: true 83 | } 84 | } 85 | }, 86 | // 为每个仅含有 runtime 的入口起点添加一个额外 chunk 87 | runtimeChunk: true 88 | }, 89 | // 性能提醒 90 | performance: { 91 | hints: false 92 | }, 93 | // 统计信息展示 94 | stats: { 95 | modules: false, 96 | children: false, 97 | chunks: false, 98 | chunkModules: false 99 | } 100 | }); 101 | 102 | module.exports = config; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{name}}", 3 | "version": "{{version}}", 4 | "description": "{{description}}", 5 | "scripts": { 6 | "start": "webpack-dev-server --config build/webpack.config.dev.js", 7 | "build": "webpack --config build/webpack.config.prod.js" 8 | }, 9 | "keywords": "{{keywords}}", 10 | "author": "{{author}}", 11 | "license": "{{license}}", 12 | "devDependencies": { 13 | "@babel/core": "^7.0.0", 14 | "@babel/plugin-proposal-class-properties": "^7.0.0", 15 | "@babel/plugin-proposal-decorators": "^7.0.0", 16 | "@babel/plugin-proposal-do-expressions": "^7.0.0", 17 | "@babel/plugin-proposal-export-default-from": "^7.0.0", 18 | "@babel/plugin-proposal-export-namespace-from": "^7.0.0", 19 | "@babel/plugin-proposal-function-bind": "^7.0.0", 20 | "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", 21 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", 22 | "@babel/plugin-proposal-optional-chaining": "^7.0.0", 23 | "@babel/plugin-proposal-pipeline-operator": "^7.0.0", 24 | "@babel/plugin-proposal-throw-expressions": "^7.0.0", 25 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 26 | "@babel/plugin-transform-runtime": "^7.0.0", 27 | "@babel/preset-env": "^7.0.0", 28 | "@babel/preset-react": "^7.0.0", 29 | "@babel/runtime-corejs2": "^7.0.0", 30 | "autoprefixer": "^9.5.1", 31 | "babel-loader": "^8.0.0", 32 | "babel-plugin-import": "^1.11.0", 33 | "clean-webpack-plugin": "^2.0.1", 34 | "css-loader": "^2.1.1", 35 | "file-loader": "^3.0.1", 36 | "friendly-errors-webpack-plugin": "^1.7.0", 37 | "html-loader": "^0.5.5", 38 | "html-webpack-plugin": "^3.2.0", 39 | "less": "^3.9.0", 40 | "less-loader": "^4.1.0", 41 | "markdown-loader": "^5.0.0", 42 | "mini-css-extract-plugin": "^0.5.0", 43 | "node-sass": "^4.12.0", 44 | "optimize-css-assets-webpack-plugin": "^5.0.1", 45 | "postcss-loader": "^3.0.0", 46 | "sass-loader": "^7.1.0", 47 | "style-loader": "^0.23.1", 48 | "uglifyjs-webpack-plugin": "^2.1.2", 49 | "webpack": "^4.29.6", 50 | "webpack-cli": "^3.3.0", 51 | "webpack-dev-server": "^3.1.4", 52 | "webpack-merge": "^4.2.1" 53 | }, 54 | "dependencies": { 55 | "antd": "^3.16.2", 56 | "mobx": "^5.9.4", 57 | "mobx-react": "^5.4.3", 58 | "moment": "^2.24.0", 59 | "prop-types": "^15.7.2", 60 | "qs": "^6.7.0", 61 | "react": "^16.8.6", 62 | "react-dom": "^16.8.6", 63 | "react-loadable": "^5.5.0", 64 | "react-router-dom": "^5.0.0", 65 | "terser-webpack-plugin": "^1.3.0", 66 | "whatwg-fetch": "^3.0.0" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lazyperson/react-quickstart-template/2ff8b844195ba9a7b61b2e399e370de6786efe72/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |