Skip to content

MillerRen/vue-scalable-app

Repository files navigation

vue-scaleable-app

短时间构建大型单页应用。所有组件按需加载,并且能够单独构建。

为什么做这个?

我们的前端应用前后端分离后,使用了单页应用,随着业务量增加,已经有上千个组件,上百个页面了,每次运行或构建都得10分钟以上, 这令人非常沮丧,在程序没有运行起来或构建期间,我觉得没有事情可做。每次开发,我只关注自己要实现的那部分,却不得不花时间在无关 的模块上,并且那些无关的模块占了大部分时间。所以我决定设计一个自己的前端模块管理系统,它应该可以单独开发和构建,并且核心应该 是稳定的,每次开发,我只需要关注一部分,而不是所有!而实现这个系统的关键,就是模块化,我把它称为分包,即与应用核心无关的东西: 插件、组件、页面都称为分包。

面临的挑战?

我要实现这样一个模块管理系统,都有哪些挑战呢?

  1. 所有的分包都是异步加载的,这意味着我不能再愉快地import了,因为这些import最终会被打包到分包中,导致分包体积巨大。
  2. 分包分离后,我仍然需要应用提供的一些能力来帮助我实现快速开发,这就需要设计一个良好的上下文传递策略。
  3. 分包需要一个管理系统,用于管理分包的部署,回退等。
  4. 需要打通开发、测试、上线的所有环节。

如何解决?

  1. 使用Vue的单文件组件作为分包的基本单元,因为Vue单文件组件可以自成一体,不必extends,也不用导入其他东西。
  2. 在分包中不允许import应用核心库,而是通过上下文获取,只允许import自己的子组件。
  3. 使用Vue的插件系统扩展核心应用能力,通过Vue.prototype传递给分包。
  4. 对于分包中经常用到的变量通过Vue的provide和inject传递。
  5. 开发一个分包管理,实现分包的分发流程管理。
  6. 分包在开发、测试、构建阶段均导出为UMD包,这样就可以无缝对接

它如何工作?

  1. 需要一个脚本加载器,用于动态加载js文件。使用requirejs实现(动态化)

  2. 需要一个配置文件,记录插件、组件、路由信息和对应js的url(配置化)

  3. 在Vue模板中声明一个组件,并在渲染时异步加载它。(按需加载)

  4. 应用和分包分离(插件,组件,路由)。(模块化)

  5. 独立构建不会随着应用规模增长而增加构建时间。(常数构建时间!)

    经过漫长而痛苦的探索,终于实现了这么一个系统,它可以在单一仓库中实现上述所有功能!在一个单体仓库(monorepo)中管理应用核心和模块。你可以把它叫做微微前端,因为它不像微前端那么复杂。所有的实现,都只是拐了一个小弯。

如何使用?

因为这个系统是倡导层次化和模块化的,因此开发人员的角色也分为核心开发和模块开发。

工具链开发

职责:设计并研发前端流程工具,比如构建系统的命令行工具,配置等。

  1. 流程工具的在线化,减少对本地工具的依赖。类似vue ui、在线代码编辑器、CI工具

对于核心开发

职责:开发核心功能和框架,并通过适当上下文暴露给分包。

  1. npm run serve
  2. npm run test:unit
  3. npm run build
  4. npm run deploy 部署后的index是带hash的类似index.asdfasddfsdfasdf.html,可以把该入口发给测试,测试通过后把它重命名为index.html这一步需要自动化

对于业务开发

职责:开发业务模块,保证业务模块反应真实业务需求。

  1. npm run serve [对应业务分包]
  2. 修改配置文件,设置分包及对应webpack server中分包入口地址如:http://localhost:8081/app.js
  3. npm run test:unit [对应业务分包]
  4. npm run package [对应业务分包]

对于分包管理者

  1. 上线前查看分包管理系统中此次上线候选的分包
  2. 选择要上线的分包并通过
  3. 通过后配置文件中的分包地址改为最新版
  4. 通知用户更新
  5. 如果分包有问题,在分包管理系统中回退

常见问题

  1. 为什么不用webpack的import()函数或require.ensure()函数来动态加载?
    因为使用这些函数会经过webpack的静态代码分析,构建时仍然是全量构建的,应用规模越大,构建时间越长
  2. 为什么使用requirejs,直接加载js文件不行吗?
    因为js文件加载后还需要插入应用上下文中去执行的,直接加载js文件则需要设计一个自己的模块管理系统。 requirjs提供了比较成熟的AMD规范,可以很方便地使用,只需要把分包构建成UMD或AMD规范导出的js就可以了, 并且webpack可以很平滑地使用AMD或UMD包。
  3. 为什么使用hash入口文件? 使用hash入口主要是为了多版本共存,你可以仅仅通过访问不同入口就可以测试不同功能。并且可以只在同一环境中测试, 避免了不同环境带来的开销。
  4. 增量式发布不会导致服务器文件太多吗? 会多,但是不会太多,前端代码文件都不会太大,并且发布到服务器的频率不会太高,像图片、视频类的文件不建议跟代码放一起,应该用单独服务器承载。即使文件比较多也没关系,静态服务器擅长这些。

About

Build huge SPA with constant time.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published