Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tim项目构建升级(一):2021-7-15 #27

Open
jsonz1993 opened this issue Jul 27, 2021 · 0 comments
Open

tim项目构建升级(一):2021-7-15 #27

jsonz1993 opened this issue Jul 27, 2021 · 0 comments

Comments

@jsonz1993
Copy link
Owner

本文为博客迁移过来,原文链接: tim项目构建升级(一):2021-7-15

项目背景

团队开发维护的tim项目,分为几个平台,分别是 pc端,app端,微信端,以及外网的一些其他页面总共四个项目。一开始是分成四个仓库维护,公用的部分发npm包维护,但是随着项目的复杂度上升,而且每周至少两个迭代的速度,npm包维护公共工具、库的形式非常繁琐。

改一个东西你需要先改公共包,你要先改包文件,然后发包构建,然后用到的地方可能app需要改,wechat需要改,pc不需要改,一天下来这套流程会浪费不少时间...

所以现在更倾向于合在一个大仓库的形式,公用的部分直接在外面写一个shard包,这样可以解决频繁改动的问题,项目件的公用部分抽离会更加方便。

但是目前app项目中的构建体系不支持这种引用外部包的形式,所以需要对app项目的构建进行一次升级,以支持shard目录的模式,后面再统一对tim-web项目的整体构建。

计划

目前的计划是先对 app 构建体系升级,去除gulp部分,然后再对这个老项目的文件目录与图片路径等进行迁移处理,最后统一用一套构建体系。

├── README.md
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── scripts
├── src
│   ├── app
│   ├── cdn
│   ├── opennet
│   ├── pc
│   ├── shared
│   └── wechat
└── tasks

构建系统升级其实就是一个发现问题,解决问题,再发现问题的螺旋上升过程。

目前APP主要的痛点是:

  • 开发体验极差,经常要等个5s-10s,而且现在功能一直在迭代,项目的复杂度直线攀升...
  • app页面有很多表单,代码每次重新构建都会刷新页面,一刷新表单数据和页面状态都消失了。如果用webpack的话,可以利用hot reload来解决这个状态问题,并且加快dev-rebuild的速度,可以大大减少同事等待构建摸鱼的时间。
  • 无法引用app之外的包,比如数据处理工具,通用逻辑,i18n多语言,通用的组件以及业务逻辑等等。目前很多数据类型的数据其实和平台无关,如果可以做到很低门槛的公用,会大大减少后续维护难度
  • gulp 开发模式一直都是构建出实体文件,对电脑性能消耗大,特别是我这种小破机,每次都不敢开太多服务...

遇到的难点其实总结为一点就是,老旧代码的迁移问题,很多代码之前在这套构建没问题,但是你一升级你得对这些旧代码做兼容处理,而且也不能手动改,因为这种构建升级的项目肯定会伴随着业务开发,你现在手动改了很多文件,后面一合代码又是白搭。所以涉及到的改动一方面要记下来,另一方面要尽可能的用脚本去改动。

app 构建升级第一版

第一版最初的设想是与pc端一致,用webpack3先取代gulp,这里总结一下升级中遇到的一些问题


css与js依赖管理

目前app项目中有许多js和css是直接引入的, 类似在 index.html中直接写了 '/public/a/to/b.js',然后文件也直接放在 'public'下面,有点像几年前手动管理依赖的味道,如果你的 jquery 放在需要依赖jq的文件下面,那页面就报错了。
所以做的第一步是把 /vendor 挪到开发目录,然后各自js和css写到一个 vendor.js vendor.css去管理。


webpack3的文档问题

webpack3目前官方没有维护文档,所以你要找对应的文档得去找网上热心网民存的快照。很多的插件也是默认安装时会报不支持 webpack < 4 的版本,而且这些插件的文档也不太好找,一个小技巧就是去npm查看这些插件的版本,然后大概猜一下webpack3需要的版本是多少,一般都是降1-2个大版本。然后再通过npm的版本去看当时这个插件的文档和使用是怎样的,这里再次标明写文档是真的很有用...


gulp.genmockConf 生成文件
这个gulp的任务是根据当前的运行模式,将一些文件的变量替换后,再输出到构建目录,然后index.html直接去引用这些文件,比如 appVersion, apiUrl等。
我们可以选择在index.js引入这些文件,然后通过 webpack.DefinePlugin 来实现,不过这次改造的目标是尽可能只动构建部分,不动代码部分。
所以我选择了用 CopyWebpackPlugin 配合 transform方法来解决这块问题。


css前缀问题

gulp 处理css的时候,老项目会在部分css变量名的前面加一个前缀,比如 .demo => .mui-demo
也就是说在写css/less的时候,是写 .demo,然后在用的时候是写 .mui-demo。而且只有部分文件需要这么处理。
这里我用了一个 postcssSelectorPrefix 的插件来解决,然后将需要加前缀的和不需要加前缀的区分开来,给需要加前缀的单独应用这个 loader。
但是这个插件有个问题,一些ionic自定义的标签转换会有问题,转换后.mui-demo的前缀自定义标签不见了,导致很多样式错乱,比如:

slide-tabs {
  font-size: 16px; 
  .demo {
    color: red;
  }
}

// 我们预期的是
slide-tabs {
  font-size: 16px;
}
slide-tabs .mui-demo {
  color: red;    
}

// 实际转换后, 
slide-tabs {
  font-size: 16px;
}
.mui-demo {
  color: red;
}

后面看了下这个东西实现不复杂,直接fork一个本地改了之后放到项目里维护了。


css 动画消失了
改完后,发现有一些动画消失了,这些动画很多是ionic改的...极其复杂,一时很难找到在哪里加的动画,加的是什么className。尝试性点即几下,发现className有快速变动,于是想到应该又是那个 className 加前缀出的问题。
首先在 chrome 调试直接给这个dom打个 break on attribute modifications,结果发现触发了n次,特别难察觉到有哪些切换,而且断点一堆也不好看...
于是换了一种思路, MutationObserver 去监听dom变化,在 class attribute变动的时候输出出来,还是没有看出什么问题。
最后用 chrome Animations面看查看运动的动画,发现果然是前缀的问题,修改了一下添加前缀的规则解决。


html 改动不触发页面reload
html是放在类似 /public/templates里面,然后通过angularJs框架运行时去请求html模板进行渲染的,所以他确实也没有参加到我们的构建服务中,这就导致一个问题。如果我们改动这些html,是不会触发reload的,需要手动刷新页面。
当下想到两种办法,第一种格式遍历所有的template,然后都写到 webpack.devServer.contentBase,虽然很hock,但是确实可以解决问题。
第二种是看webpackDevServer.watch是怎么处理的,看如何解决这个问题,发现 watch依赖的是 [email protected],这个版本已经被废弃了基本无解,所以最后决定用 glob扫出 public/template的文件加到contentBase中,曲线救国...等后面升级webpack版本就好了。

至此,第一版基本完成,和同事讨论之后,同事说这种改造测试起来很废时间,还不如一步到位直接上webpack5好一点...我被说服了...

app 构建升级第二版

第二版直接在第一版的基础上升级webpack的版本,所以总体会感觉轻松一些。但是毕竟升级了两个大版本,问题还是不少。


arguments is not defined

升级完webpack5之后的第一个问题就是,代码报错,报了 arguments is not defined,报错的地方是一个依赖的包,这个报错的原因是 webpack4之前,包裹模块的函数是函数表达式,而webpack4以后改为了箭头函数,所以其实问题一直都存在,只是以前没有暴露出来。
这个问题也好解决,直接升级该包的版本就可以了。


esm和cjs混写问题
旧项目很多是esm和cjs混着写,因为angularJs的依赖注入需要用 cjs,所以一开始是想着用一个脚本去分析ast,然后都改为cjs。后面想着不应该,于是各种找资料,然后在本地直接用 babel编译cjs和esm混用的代码,发现没有报错。最后通过改了babel的配置解决。


production 模式报错
开发测试成功之后,开始自测构建生产环境的代码,发现如果 mode:development一切正常,但是改成production的时候就会一直报 angularJs 模块注入的错误。
这个比较好解决,既然都知道是mode的问题,直接去webpack官网看这两种模式的配置区别是什么,一个一个排除之后发现是代码压缩导致的,修改下配置,去掉 mangle选项后解决。不过具体的原因目前还没有了解。

minimizer: [
	new TerserPlugin({
		terserOptions: {
			mangle: false
		}
	})
]

总结

期间还遇到其他配置等问题,无脑刷官网就可以解决了。

目前改造后未深度优化的效果:
老项目:

  • 首次构建:33940ms
  • 开发编译:5004ms
  • 生产构建: 49479ms
  • 打包后www目录大小: 31M

改造后:

  • 首次构建: 11184ms
  • 开发编译: 1462ms
  • 生产构建: 56634ms (这就有点尴尬了)
  • 打包后www目录大小: 11M

我觉得最大的作用还不是构建速度和代码大小的问题,最大的作用是为后面很多新特性和改造奠定了根基。

下一步的工作是:

  • 图片、字体等资源纳入构建系统中
  • 文件夹目录统一
  • tim-web的另外几个项目构建升级
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant