首先我是很赞同业界的先后端分离的开发模式,虽然如今都讲究全栈工程师,可是毕竟术业有专攻,前端同窗专一多终端,后端同窗关注高性能高可用。你们各自再本身的专一点上发光发热。css
想一想咱们之前分模块开发,既写java又写jsp,高级点的jsp不写逻辑,全部的交互都是异步交互,算是一个简单的先后端分离模型,最后找个美工(对,不是前端是写css或者会画图的美工画两个图)美化一下,而后就能够用起来了,这样的模式简直就是原始社会同样。前端
目前我同时接手了先后端同窗给个人2份代码后,一我的作起了先后端分离开发,我感受本身一会儿高大上了起来,可是有几点我也要吐槽一下java
1我要维护2分代码,一份用webstorm编译js代码,一份用intelidea开发编译java代码,同时开了java和node服务本地联调,这2个服务光开起来就已经7G内存了(jvm我开的是1024M,由于须要加载对象内存处理)。可怜的X1的内存是焊死的...焊死的....,并且只有8G....基本再开chrome就卡死了,卡死了。。。node
2 本地开发模式是这样的,前端代码用node开启一个server跑页面,后端代码开启跑接口服务,用页面调用后端的接口服务,这就遇到一个尴尬的js跨域调用服务的问题,还好chrome良心支持这个参数,又还好IE咱们已经放弃了。。。react
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --args --disable-web-security --user-data-dir
可是由此升级chrome到51这个版本,新浏览器又出现跨域调不通的问题了,那时个人世界是崩溃的,之后怎么开发吖webpack
还好网上有解决方案,感谢万能的google,对于新版本的chrome浏览器,须要额外增长user-data-dir,而后就能够继续愉快的写代码了git
这里我还要吐槽下之前的npm脚本github
"scripts": { "clean": "./node_modules/.bin/rimraf build", "build:webpack": "NODE_ENV=production ./node_modules/.bin/webpack --config webpack.config.prod.js", "build": "npm run clean && npm run build:webpack", "mock": "MOCK=true npm run start", "start": "./node_modules/node/bin/node server.js", "lint": "./node_modules/.bin/eslint src", "lintfix": "./node_modules/.bin/eslint src --fix", "daily": "npm run build && git add -A && git commit -am 'deploy test' && git branch -D daily/9.9.9 || true && git branch daily/9.9.9 && git push -f origin daily/9.9.9 && git reset --hard HEAD~" },
看里面的反斜线,好像windows都不能用吖,只能本身搞个bat脚本封装下,基本上再window下告别npm命令了web
echo "====start daily publish" call .\node_modules\.bin\rimraf build set NODE_ENV=production call .\node_modules\.bin\webpack --config webpack.config.prod.js call git add -A call git commit -m 'dailypublish' call git branch -D daily/9.9.9 call git branch daily/9.9.9 call git push -f origin daily/9.9.9 echo "====end daily publish"
3 最后吐槽一下发布和回滚问题sql
有段时间需求实在太多,团队增长一个同窗一块儿开发,注意下前端这块,咱们都是用分支开发,发到预发的时候代码是都要合并到daily9.9.9这个分支的,而后触发一个钩子,这个钩子会把这9.9.9的代码放到cdn上,就是2个会合用一个分支,预发环境常常是代码被各类冲掉,这个后端的开发和发布系统支持的就好,环境只有一个,可是每次发布只能发一个分支。这样能够各类切换,而不是暴力的合并
另外,因为后端代码一次发布可能会有屡次的前端发布,因此前端的版本号实际上是和后端的版本号不一致的,若是线上出了故障,后端代码进行回滚我可能准确的回滚到一个版本,可是前端代码的版本号是跳跃的,很难回滚到后端同一时刻的版本
4 最后就是接口和代码设计的问题
因为先后端代码是不一样同窗开发的,当前端A同窗须要一个列表数据会跟后端B同窗要一个get接口,这时候B同窗提供一个接口服务返回一串数据给前端,我看过一个以前的代码前端拿到这个数据活生生的在前端作了一个排序,各类map各类比较,其实这个在后端数据库层面或者内存层面作一下很是简单。
5 最后讲讲编译问题
以前我手上还有一个项目,也是先后端代码分开的,这个比较特殊,前端是GXT写的,恩就是用java写的EXT,写前端的页面的时候很是痛苦,GXT的编译特别慢,有的时候改一个页面编译一下要1分钟,另外发布的时候很是原始,写好GXT的代码把代码打包成war包,而后copy出里面的静态页面再放到后端代码里,后端代码再打成war包进行发布
相比如今来讲现有项目已经很好了,前端写好代码push到指定分支上就能自动部署到cdn上,而后后端的vm直接读取cdn上的静态资源。可是后端的发布每每要等cdn部署完毕才能真正生效,根本缘由仍是不是引得本地文件
由于实在感受如今本地开发模式效率有点低(真正项目里咱们仍是要作先后端分离的哈),我花了2天的时间对现有的项目进行了一下改造,就是将先后端代码合并起来,这里就简单的介绍下如何用再一个项目里同时维护先后端代码
这里涉及到webpack打包操做,用mvn进行npm操做,前台代码的热部署及前端代码的合并分发
1 线上改造后的代码结构
其中node是maven下运行npm的插件引入的,node_modules是前端依赖包(能够理解成java中maven引入的本地仓库),将原有的前端文件放到了webapp中
其中build是webpack打包生成的输出文件,index页面引用的就是这里的合并后的js和css,app.js是前端的入口文件
其余文件就是后台和前端的配置文件了,前端的主要打包文件是webpack.config
2 定义npm的打包命令
"mydaily":".\\node_modules\\\\.bin\\webpack-dev-server --config webpack.config.js --inline ", #"mydaily":".\\node_modules\\\\.bin\\webpack --config webpack.config.js --hot --progress --colors --watch", "mybuild":".\\node_modules\\\\.bin\\webpack --config webpack.config.js --output-public-path /build/", "myclean": ".\\node_modules\\\\.bin\\rimraf .\\src\\main\\webapp\\build", "mystart": ".\\node_modules\\node\\bin\\node server.js",
其中mydaily定义的的是的本地开发模式,mybuild是打包线上发布文件,myclean是清除文件,mystart是为了兼容前端开发同窗保留的命令,直接用node本地启动服务,固然还有一些其余的调用eslint等辅助控件这里就不一一列出了
3 本地开发模式下如何引用前端输出的静态资源呢
indexvm里是这么写的
## <link rel="stylesheet" href="http://localhost:8080/build/style.css"/> ## <script src="http://localhost:8080/build/vendors.js"></script> ## <script src="http://localhost:8080/build/app.js"></script>
这里有个关键的启动命令,本地在npm的时候使用的是webpack-dev-server。这个命令能够虚拟出一个服务,而且配置了热加载,咱们能够看到文件的publicpath配置的就是8080端口下的这个地址
output: { path: path.resolve(__dirname, 'src/main/webapp/build'), filename: '[name].js', publicPath: 'http://localhost:8080/build/', },
若是是线上发布,就直接启动webpack,将文件编译好发布到build文件夹
4 如何作前端资源热加载的,这里有2个地方要配置下
一是使用一个jsx的loader使用的react-hotloader
二是配置idea的自动监听功能
这样就能够作到热部署了
5 如何用maven维护npm的打包和编译呢
这里就要提到mavne下一个插件了frontend-maven-plugin,由于不管是线上aone打包仍是线下打包其实调用的都是mvn clean install命令,这时候会自动触发这个插件中的命令,我本地的配置以下
<!--前端打包--> <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.0</version> <executions> <execution> <id>install node and npm</id> <goals> <goal>install-node-and-npm</goal> </goals> <configuration> <nodeVersion>v5.2.0</nodeVersion> <npmVersion>3.3.0</npmVersion> <nodeDownloadRoot>https://npm.taobao.org/mirrors/node/</nodeDownloadRoot> <npmDownloadRoot>http://registry.npmjs.org/npm/-/</npmDownloadRoot> </configuration> </execution> <execution> <id>npm install</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>install</arguments> </configuration> </execution> <execution> <id>npm run build</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>run mybuild</arguments> </configuration> </execution> </executions> </plugin>
这个插件会在maven命令执行的时候自动执行配置好的npm命令,因此在打包的时候就会自动触发npm run mybuild命令打包最新的静态资源到war包中,这样就无需在引用cdn中的文件了
通过以上5部改造,基本上能够实现先后端代码同时维护和开发,保证了本地开发的效率。可是将来多端及服务化,先后端分离仍是大趋势,咱们仍是要尽可能摒弃小做坊的开发模式,让代码在稳定的基础上最大的保证开发效率。另外仍是要像全栈开发努力,由于不少功能前端作起来很容易,可是后端要写一大堆不可维护的代码来实现,有的时候前端要作很复杂的代码,后端可能一个sql就搞定了。