背景最近接了个新项目, 遇到一些问题, 在这整理分享下。前期规划需求是这样的,需要做一套后台管理系统: 一个主系统,一个子系统,开发时间6个周。 前期开发有两个人, 再加一个人。
说实话时间有点紧, 所以前期做好规划就很重要。 实现先做一个规划,技术选型,文档分析,分页面, 有个大致的评估。
技术选型首先确定的还是 React 这一套, 即: React,Redux,TypeScript, 样式管理 styled-components, 国际化 react-intl, 组件库 antd, 脚手架,自己配。 本来想图省事用 CRA(create-react-app),后来觉得用rewired 重写不太灵活, 而且有个小伙伴也想自己配,熟悉下 webpack , 还是决定自己搭, 后面会把配置贴出来。
开发计划和后端负责人讨论之后决定把这一期的开发任务分成三个小阶段: P1, P2, P3
P1 完成之后发布, 先跑通主流程,P2 P3 继续迭代功能。 P1 主要包括:
开发环境搭建test环境资源申请Nginx 配置主系统功能开发
三个功能模块开发登陆注册流程子系统两个模块的开发开发时间: 两周
压力还是有的,时间紧,任务重,而且是第一次带人做项目, 好在内心犹如一条老狗,一点都不慌。
后面就进入了开发阶段, 遇到了挺多问题。
进入开发搭建开发环境这一步大家就都很熟悉了,添加各种配置和打包。 因为主系统和子系统页面风格都是一样的, 没必要分成两个系统, 把新开一个文件夹,里面放子系统的页面, 然后打成不同的包就可以了。就有了如下配置:
// webpack.config.jsconst path = require('path')const HtmlWebpackPlugin = require('html-webpack-plugin')const webpack = require('webpack')const fs = require('fs')const lessToJS = require('less-vars-to-js')const { NODE_ENV } = process.envconst isAdminApp = process.env.APP_TYPE === 'admin'const getBaseurl = () => { switch (process.env.ENV) { case 'id': return 'https://xxx.test.shopee.co.id' default: return '' }}const plugins = [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'template.html'), title: isAdminApp ? 'WMS LITE ADMIN' : 'WMS LITE', }), new webpack.DefinePlugin({ __BASEURL__: JSON.stringify(getBaseurl()), }), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)]if (NODE_ENV !== 'production') { plugins.push(new webpack.SourceMapDevToolPlugin({}))}const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './assets/antd-custom.less'), 'utf8'))const port = isAdminApp ? 9527 : 8080module.exports = { entry: [ '@babel/polyfill', isAdminApp ? './admin/index.js' : './pages/index.js' ], output: { filename: isAdminApp ? 'admin.[hash:8].js' : 'main.[hash:8].js', path: path.resolve(__dirname, isAdminApp ? 'dist/adminstatic' : 'dist/static'), publicPath: isAdminApp ? '/admin/' : '/', }, mode: NODE_ENV, devtool: false, plugins, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, { test: /\.less$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'less-loader', options: { javascriptEnabled: true, sourceMap: true, modifyVars: themeVariables, }, } ], }, { test: /\.css$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', } ], }, { type: 'javascript/auto', test: /\.mjs$/, use: [], }, { test: /\.(png|jpg|gif|svg)$/i, use: [ { loader: 'url-loader', options: { limit: 8192, }, } ], } ], }, optimization: { runtimeChunk: { name: 'manifest', }, splitChunks: { chunks: 'all', minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, cacheGroups: { vendor: { test: /[\\/]node_modules/, filename: 'vendor.[chunkhash:8].js', enforce: true, priority: 5, }, antd: { test: /[\\/]node_modules[\\/]antd[\\/]/, filename: 'antd.[chunkhash:8].js', priority: 10, }, antdIcons: { test: /[\\/]node_modules[\\/]@ant-design[\\/]/, filename: 'antd-icons.[chunkhash:8].js', priority: 15, }, styles: { test: /\.(scss|css)$/, filename: 'styles.[hash:8].css', minChunks: 1, reuseExistingChunk: true, enforce: true, priority: 20, }, }, }, }, devServer: { historyApiFallback: isAdminApp ? { rewrites: [{ from: /.*/g, to: '/admin/index.html', }], } : true, hot: true, port, proxy: [{ context: ['/admin/api', '/api'], target: 'https://gudangku.test.shopee.co.id', changeOrigin: true, onProxyRes(proxyRes, _, res) { const cookies = proxyRes.headers['set-cookie'] || [] const re = /domain=[\w.]+;/i const newCookie = cookies.map(cookie => cookie.replace(re, 'Domain=localhost;')) res.writeHead(200, { ...proxyRes.headers, 'set-cookie': newCookie, }) }, }], },}// package.json "scripts": { "start": "NODE_ENV=development APP_TYPE=main webpack-dev-server", "build": "NODE_ENV=production APP_TYPE=main webpack", "start:admin": "NODE_ENV=development APP_TYPE=admin webpack-dev-server", "build:admin": "NODE_ENV=production APP_TYPE=admin webpack", "lint": "eslint ./ --ext js", "i18n": "node i18n/index.js" },根据不同的参数打包, 主系统打包到 dist/static, 子系统打包到dist/adminstatic. ...