目前的构建系统,区分了生产环境和开发环境,现在的开发环境构建是没有什么问题的。 但是开发环境问题就比较明显,存在的最大问题是服务端没有热更新或者重新打包重启。 这样会导致很多问题,最严重的就是前端已经更新了组件,但是服务端并没有更新,所以在同构的时候会出现不一致,就会导致报错,有些报错会影响运行,解决办法只有重启。 这样的开发体验是无法忍受的。 后来我开始考虑做服务端的热更新。
监听、打包、重启
最初我的方法是监听修改,打包然后重启应用。 还记得我们的client/router/pages.js文件吗,客户端和服务端的路由都引入了这个文件,所以服务端和客户端的打包依赖都有pages.js,因此所有pages的组件相关的依赖都可以被客户端和服务端监听,当一个组件更新了,dev-server已经帮助我们监听和热更新了客户端代码,现在我们要自己来处理以下如何更新和重启服务端代码。 其实方法很简单,就是在服务端打包配置里开启监听,然后在插件配置中,写一个重启的插件,插件代码如下:
当webpack首次运行之后,插件会启动一个子进程,运行app.js,当文件发生变动后,再次编译,判断是否有子进程,如果有杀掉子进程,然后重启子进程,这样就实现了自动重启。 因为客户端和服务端是两个不同的打包服务和配置,当文件被修改,他们同时会重新编译,为了保证编译后运行符合预期,要保证服务端先编译完成,客户端后编译完成,所以在客户端的watch配置里,增加一点延迟,如下图,默认是300毫秒,所以服务端是300毫秒后执行编译,而客户端是1000毫秒后执行编译。
现在解决了重启问题,但是我觉得还不够,因为在开发的大部分时间里pages.js中组件,也就是展示端的代码更新频率会很高,如果老是去重启编译后端的代码,我觉得效率太低。 因此我觉得再做一次优化。
抽离client/router/pages单独打包
流程应该是这样的,增加一个webpack.server-dev-pages.js配置文件,单独监听和打包出dist/pages,服务端代码判断如果是开发环境,在路由监听方法中每次执行都重新获取dist/pages包,服务端监听配置忽略client文件夹。 看起来有点懵逼,其实最终的效果就是当pages中依赖的组件发生了更新,webpack.server-dev-pages.js重新编译并打包到dist/pages中,服务端app不编译和重启,只需要在服务端app路由中重新获取最新的dist/pages包,就保证了服务应用更新了所有客户端组件,而服务端应用并不会编译和重启。 当服务端本身的代码发生了修改,还是会自动编译和重启。 所以最终我们的开发环境需要启动3个打包配置
webpack.server-dev-pages
webpack.server-dev
webpack.client-dev
server/router,如何清除和更新pages包
至此,比较满意的开发环境基本实现了。 后来又觉得每次更新css都需要去重新打包后端的pages也没有必要,加上同构的时候css不一致,仅仅只有警告,没有实质影响,因此我在server-dev-pages中忽略了less文件(因为我用的less)。 这样会导致一个问题,因为没有更新pages,所以页面会刷新时会先展示旧的样式,然后同构完成又立马变成新样式,在开发环境中这一瞬间是可以接受的,也不影响什么。 但是避免了无谓的编译。
没有做的事情
封装成一个更有包裹性的三方脚手架
css作用域控制
封装性更强的webpack配置
开发环境下,图片路径会出现不一致
最初做自己小站的目的是学习,加上自己使用,因此有太多个性的东西。 从自己的小站中抽离了出来,已经删去了很多包和代码,只为了让他人更能快速理解其中的核心代码。 代码中有很多注释都能帮助他人理解,如果大家想使用当前库开发一个自己的小站,是完全可以的,也可以帮助大家更好的理解它。 如果是用于商业项目,推荐nextjs。 css没有做作用域控制,因此如果想隔离作用域,手动添加上层css隔离,比如.index{ ..... }包裹一层,或者尝试自己引入三方包。 webpack通用的配置可以封装成一个文件,然后在每个文件里引入,再个性修改。 但是之前看其他代码的时候发现,这种方法,会增加阅读难度,加上本身配置内容不多,所以不做封装,看起来更直观。 开发环境下,图片路径会出现不一致,比如客户端地址请求地址是localhost...assets/xx.jpg,而服务端是assets/xx.jpg,可能会有警告,但是不影响。 因为只是一个是绝对路径,一个是相对路径。
最后