互相交流学习,请加我微信: iyangyuanjian,QQ:624508914
1、前言
- 该项目是公司内部服务与外部服务的中台系统,我称之为大杂烩
- 项目始于:2015年10月8号 18:31:39秒
- 恩,没错,到写文章为止,已经迭代了整整 3年2个月18天
2、为什么要升级?
- 因为实在是太慢了,删除缓存的情况下,要编译启动起来得花
250
秒 - 有缓存的情况下启动得
120
多秒 - 热更新也慢得
10
秒左右 - 发布就更不用说了,都是泪,出了 BUG 要修复的话,最少得等 20 分钟才能修复
3、升级之后达到的效果
- 没有缓存的情况下编译启动
40
秒左右 - 有缓存的情况下编译启动
20
秒左右 - 热更新
1 ~ 3
秒
4、老项目架构
express
webpack
react
redux
- 具体请看
package.json
在尾部
5、新项目架构
- 基本不变,做了很多启动时的调整和优化
6、踩坑之路开始
6.1、梳理 package.json
- 把一些老项目中没有用到的包给干掉
- 区分清楚 dev 依赖
6.2、创建新的开发环境
- babel + webpack + express + react + react-redux 都是最新版, 其余的升级后面再看
- react-router 升级到 3.x 最新版(支持 react 16.x )
- 相关包在测试中慢慢升级
- 自动监听端口是否被暂用,端口暂用后可以输入新端口启动
- 启动之后自动打开浏览器
上面两部流程完了之后,开始迁移老项目到新开发环境中,不要直接在老项目改动
6.3、老项目测试启动
- 之前老项目存在 typescript 写法,居然可以正常运行这么多年,奇葩,关键还能编译成功,批量替换掉
- 删除
package.json
中没有被应用 - 发现系统大量用了
react
的PropTypes
,在 16 之后就拆分成单独的包了,批量替换成新包 - 有一些
babel
语法问题,找方法修复 - 嗯,顺利启动
总结
- 其中过程曲折太多了,尝试了两个礼拜,期间进行了 5-6 次升级尝试
- 作为一个后端,我感觉要学的东西太多了,有种有心无力的感觉
- 整个项目最难的地方在于
babel
因为是老项目,存在module.exports
写法,以及一些其他的配置,都是临时看官方文档,谷歌,Stack Overflow去找解决方案,当然也受益匪浅 - 还有些老项目的东西需要完成,比如
eslint
,typescript
接入,打包发布
新项目的 package.json
{
"name": "xxx 敏感信息",
"version": "1.0.0",
"description": "xxx 敏感信息",
"repository": "xxx 敏感信息",
"author": "smithyj<[email protected]>",
"private": true,
"scripts": {
"start": "webpack-dashboard -- npm run start:pure",
"start:nodemon": "webpack-dashboard -- npm run start:pure:nodemon",
"start:pure": "cross-env NODE_ENV=development babel-node ./server/app.js",
"start:pure:nodemon": "cross-env NODE_ENV=development nodemon ./server/app.js --exec babel-node",
"build": "npm run build:prod",
"build:prod": "cross-env NODE_ENV=production webpack",
"build:test": "cross-env NODE_ENV=test webpack",
"serve": "cross-env BUILD_SERVE=true npm run build:test && serve dist",
"rsync:remote:test": "xxx 敏感信息",
"rsync:remote:prod": "xxx 敏感信息",
"deploy:remote:test": "npm run build:test && npm run rsync:remote:test",
"deploy:remote:prod": "npm run build:prod && npm run rsync:remote:prod",
"deploy:remote": "npm run deploy:remote:test && npm run deploy:remote:prod"
},
"devDependencies": {
"@babel/cli": "^7.2.0",
"@babel/core": "^7.2.0",
"@babel/node": "^7.2.0",
"@babel/plugin-proposal-class-properties": "^7.2.1",
"@babel/plugin-proposal-decorators": "^7.2.2",
"@babel/plugin-proposal-do-expressions": "^7.2.0",
"@babel/plugin-proposal-export-default-from": "^7.2.0",
"@babel/plugin-proposal-export-namespace-from": "^7.2.0",
"@babel/plugin-syntax-decorators": "^7.2.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.2.0",
"@babel/polyfill": "^7.0.0",
"@babel/preset-env": "^7.2.0",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.4",
"babel-plugin-add-module-exports": "^1.0.0",
"body-parser": "^1.18.3",
"cache-loader": "^1.2.5",
"chalk": "^2.4.1",
"clean-webpack-plugin": "^1.0.0",
"clipboardy": "^1.2.3",
"cookie-parser": "^1.4.3",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.2.0",
"css-loader": "^2.0.1",
"detect-port": "^1.3.0",
"express": "^4.16.4",
"extract-css-chunks-webpack-plugin": "^3.2.1",
"file-loader": "^2.0.0",
"happypack": "^5.0.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"mini-css-extract-plugin": "^0.5.0",
"morgan": "^1.9.1",
"nodemon": "^1.18.8",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"progress-bar-webpack-plugin": "^1.11.0",
"react-dev-utils": "^6.1.1",
"serve": "^10.1.1",
"serve-favicon": "^2.5.0",
"style-loader": "^0.23.1",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2",
"webpack-dashboard": "^2.0.0",
"webpack-dev-middleware": "^3.4.0",
"webpack-hot-middleware": "^2.24.3",
},
"dependencies": {
"ali-oss": "^5.2.0",
"antd": "^2.13.10",
"autobind": "^1.0.3",
"core-decorators": "^0.20.0",
"create-react-class": "^15.6.3",
"jump.js": "^1.0.2",
"lodash": "^4.16.4",
"lodash-decorators": "^4.5.0",
"md5": "^2.2.1",
"moment": "^2.19.4",
"pdfjs-dist": "^1.9.528",
"prop-types": "^15.6.2",
"qrcode.react": "^0.7.2",
"query-string": "^6.2.0",
"rc-queue-anim": "^1.6.10",
"rc-tween-one": "^1.7.2",
"react": "^16.7.0",
"react-addons-update": "^15.6.2",
"react-color": "^2.14.1",
"react-copy-to-clipboard": "^5.0.1",
"react-dnd": "^2.1.2",
"react-dnd-html5-backend": "^2.1.2",
"react-dom": "^16.7.0",
"react-drag-listview": "0.0.9",
"react-mixin": "^5.0.0",
"react-redux": "^6.0.0",
"react-router": "^3.2.1",
"react-string-replace": "^0.4.0",
"redux": "^3.3.1",
"redux-form": "^5.3.3",
"redux-logger": "^2.7.0",
"redux-promise": "^0.5.3",
"redux-thunk": "^1.0.0",
"simditor": "2.3.22",
"simditor-fullscreen": "^0.1.1",
"simditor-html": "^1.1.1"
}
}
复制代码
老项目的 package.json
{
"name": "crm",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "webpack-dashboard -- cross-env NODE_ENV=development node ./server/bin/www",
"start:pure": "NODE_ENV=development node ./server/bin/www",
"clean": "rimraf client/dist/",
"clean:cache": "rimraf ./.cache",
"build": "cross-env BABEL_ENV=production webpack --config webpack.config.js",
"build:test": "NODE_ENV=test npm run build",
"build:prod": "NODE_ENV=production npm run build",
"rsync:test": "xxx 敏感信息",
"rsync:prod": "xxx 敏感信息",
"deploy:test": "npm run build:test && npm run rsync:test",
"deploy:prod": "npm run build:prod && npm run rsync:prod",
"rsync:remote:test": "xxx 敏感信息",
"rsync:remote:prod": "xxx 敏感信息",
"deploy:remote:test": "npm run build:test && npm run rsync:remote:test",
"deploy:remote:prod": "npm run build:prod && npm run rsync:remote:prod",
"deploy:remote": "npm run deploy:remote:test && npm run deploy:remote:prod",
"lint": "eslint --ext .js --ext .jsx client/src",
"fix": "eslint --fix --ext .js --ext .jsx client/src",
"prettier:fix": "prettier --write '**/*.{js,jsx,less,css.scss,html}'",
"prebuild": "npm run clean",
"commit": "commit-wizard"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,less,css,scss,html}": [
"prettier --write",
"git add"
],
"*.{js,jsx}": [
"eslint --fix",
"git add"
]
},
"dependencies": {
"ali-oss": "^5.2.0",
"antd": "^2.13.10",
"assets-webpack-plugin": "^3.4.0",
"autobind-decorator": "^2.1.0",
"axios": "^0.15.3",
"bluebird": "^3.3.4",
"body-parser": "^1.15.1",
"connect-multiparty": "^2.1.0",
"cookie-parser": "~1.4.0",
"core-decorators": "^0.20.0",
"css-loader": "^0.28.7",
"debug": "~2.2.0",
"del": "^3.0.0",
"express": "^4.14.0",
"fs-extra": "^4.0.3",
"genny": "^0.5.6",
"glob": "^7.0.0",
"hbs": "~4.0.0",
"history": "^1.13.0",
"html-webpack-plugin": "^1.6.2",
"immutable": "^3.7.5",
"jump.js": "^1.0.2",
"less": "^2.7.3",
"less-loader": "^4.0.5",
"lodash": "^4.16.4",
"lodash-decorators": "^4.5.0",
"logrocket": "^0.5.2",
"md5": "^2.2.1",
"method-override": "*",
"moment": "^2.19.4",
"morgan": "^1.6.1",
"nodejieba": "^2.2.4",
"pdfjs-dist": "^1.9.528",
"pinyin": "^2.8.0",
"qrcode.react": "^0.7.2",
"raw-loader": "*",
"rc-animate": "^2.4.4",
"rc-queue-anim": "^0.12.6",
"rc-tween-one": "^1.7.2",
"react": "15.3.1",
"react-addons-css-transition-group": "^15.6.2",
"react-addons-update": "^15.6.2",
"react-color": "^2.14.1",
"react-copy-to-clipboard": "^5.0.1",
"react-dnd": "^2.1.2",
"react-dnd-html5-backend": "^2.1.2",
"react-dom": "15.3.1",
"react-drag-listview": "0.0.9",
"react-froala-wysiwyg": "^2.8.1",
"react-loadable": "^4.0.5",
"react-mixin": "^4.0.0",
"react-pure-render": "^1.0.2",
"react-redux": "^5.0.6",
"react-router": "^2.8.1",
"react-string-replace": "^0.4.0",
"redbox-react": "^1.5.0",
"redux": "^3.3.1",
"redux-form": "^5.3.3",
"redux-logger": "^2.7.0",
"redux-promise": "^0.5.3",
"redux-thunk": "^1.0.0",
"rimraf": "^2.4.3",
"serve-favicon": "^2.4.5",
"simditor": "^2.3.19",
"simditor-fullscreen": "^0.1.1",
"simditor-html": "^1.1.1",
"text-loader": "*",
"url-loader": "^1.0.1"
},
"devDependencies": {
"babel-core": "^6.18.0",
"babel-eslint": "^8.2.1",
"babel-loader": "^7.1.2",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-import": "^1.6.3",
"babel-plugin-lodash": "^3.3.2",
"babel-plugin-react-transform": "^3.0.0",
"babel-plugin-transform-class-properties": "^6.16.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-polyfill": "^6.16.0",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.16.0",
"babel-preset-es2015-loose": "^8.0.0",
"babel-preset-react": "^6.16.0",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-0": "^6.16.0",
"babel-standalone": "^6.4.4",
"clean-webpack-plugin": "^0.1.8",
"cross-env": "^5.1.3",
"eslint": "^4.15.0",
"eslint-config-prettier": "^3.3.0",
"eslint-config-standard": "^10.2.1",
"eslint-config-standard-jsx": "^4.0.1",
"eslint-config-standard-react": "^5.0.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-react": "^7.5.1",
"eslint-plugin-standard": "^3.0.1",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.6",
"husky": "^1.2.0",
"lint-staged": "^8.1.0",
"prettier": "^1.15.2",
"progress-bar-webpack-plugin": "^1.3.0",
"react-hot-loader": "^3.1.3",
"react-router-loader": "^0.5.4",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.4",
"source-map-loader": "^0.2.1",
"style-loader": "^0.19.0",
"transfer-webpack-plugin": "^0.1.4",
"uglifyjs-webpack-plugin": "^1.1.6",
"webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.2",
"webpack-dashboard": "^0.4.0",
"webpack-dev-middleware": "^1.12.2",
"webpack-dev-server": "^2.10.1",
"webpack-hot-middleware": "^2.21.0",
"webpack-md5-hash": "^0.0.5",
"workbox-webpack-plugin": "^1.0.1"
},
"engines": {
"node": ">=6"
}
}
复制代码