学习笔记本 - 前端工程化
type: channel
link: http://175.24.197.152/tag/%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%8C%96/
items: Monorepo模式
items: 前端权限开发——设计到实践
items: rollup.js的个人理解
items: 前端工程化的思考

Monorepo模式
type: item
date: 2024-02-08T07:19:00+00:00
description: 什么是 Monorepo？一个 Monorepo 是一个单一的存储库，包含 多个不同的项目 ，和 明确的关系 。和 Monorepo 对立的是传统的 Polyrepo 模式，每个项目对应一个单独的仓库来分散管理现代的前端工程越来越多的都会选择 Monorepo 的方式进行开发，比如 Vue、React 等知名开源项目都采用的 Monorepo 的方式进行管理。Monorepo 的组织方式如下├── packages | ├── pkg1 | | ├── package.json | ├── pkg2 | | ├── package.json ├── package.json在 packages 目录下存放多个子项目，当然也可以叫其他名字，每个子项目都有自己的 package.json 文件，用来管理子包。在更换新的方式之前，一定要知道原先的方式有什么缺点。接下来就先聊聊 Polyrepo 的方式在生产上都存在着哪些弊端。Polyrepo 的弊端1. 代码重复Polyrepo 容易导致代码重复，主要是因为不同的项目都有自己的独立代码仓库。在维护一些基础组件或者工具函数时，会想着直接从 A 仓库将代码复制到 B 仓库里使用，这样很方便，但是却给后续维护成本带来了很大的负担。一旦出现需要修改的地方，需要在 多个仓库中进行修改 ，这可能会导致修改过程出现错误，并可能导致代码的不一致。那么当然我们可以不进行复制，将公共逻辑抽离出来，单独发包，作用一个 npm 模块引入到项目中，需要修改时，也只用修改一份代码，然后重新发布即可。但是这整个流程还是太复杂了，并不是完美的解决方式，仅仅是为了修改一点点东西，就需要去发包、更新，这太麻烦了。小结：不同仓库之间的割裂感、导致复用代码的成本很高，开发体验差。或者需要在多个仓库中重复编写相同的代码，从而导致代码的不一致性和冗余性。2. 版本管理因为多个仓库分别管理自己的代码，这样会缺乏一个 全局视角去看待所有仓库 ，无法清晰的了解到整个项目的结构和状态。当不同仓库中的有依赖关系时，会有依赖管理的问题，时时刻刻都需要注意依赖的版本和代码是否一致例如：主项目依赖了子项目提供的组件，如果此时子项目在某次升级时产生了 breaking change 版本，和原来的组件使用方式完全不一致，这样主项目就直接寄了。因此我们需要在子项目更新时，及时的更新主项目的依赖，这样就形成了负担。当组件出现异常时，就会开始怀疑包版本是否不正确...因此，Polyrepo 需要有合适的版本管理方法，保证版本和代码的一致性3. 工具混乱每个项目都使用自己的一组命令来运行测试、构建、服务、检查、部署等。不一致会导致记住在不同项目中使用哪些命令的心理负担。单独部署、独立工作流在多仓库情况下，由于在不同的仓库里，继承测试会变得更加的困难，需要很多步骤才能组合在一起测试。同时每个项目都使用自己的一组命令来运行测试、构建、服务、检查、部署等。不一致会导致记住在不同项目中使用哪些命令的心理负担，维护起来也是问题例如：每个项目都会配置自己的 webpack.config.js 文件，但是这些配置很多都是一致的。例如：CI、CD 流程很难将多个仓库组合到一起去，测试也比较难处理4. 代码共享要跨存储库共享代码，可能会为共享代码创建一个存储库。那么必须设置工具和 CI 环境，将提交者添加到存储库，并设置包发布以便其他存储库可以依赖它。让我们不要开始跨存储库协调第三方库的不兼容版本....5. 代码管理基于 Polyrepo 管理，每个开发人员的 commit 都会提交到各个仓库，不利于代码的 CR，也不利于管理代码合入机制，导致容易出现逃逸现象。Monorepo 能解决什么问题？Monorepo 都能解决以上的问题不仅仅在于减少了维护和管理多个代码库的成本，同时还有以下优点：代码复用 ：因为多个项目共享一个代码库，所以避免了在不同项目中重复编写相同功能代码的问题，提高了开发效率。提升协作效率 ：多个项目在同一个代码库中进行开发，可以方便地共享代码和文档，避免不同项目之间的沟通和协调成本。集中管理 ：Monorepo 架构中，不同的应用程序都在同一个代码库中，方便管理和监控。这一点非常重要，特别是在需要同时对多个版本进行修改和维护的情况下。统一构建 ：Monorepo 的一个重要特点是可以共用一套构建系统和 工具链进行构建和部署 ，提升了构建的效率。可以快速定位问题 ：由于所有的代码都在同一个代码库中进行开发，debugger 可以很快找出问题所在的代码文件和行数，便于开发人员调试问题。一个版本 ：无需担心因为项目依赖于第三方库的冲突版本而导致的不兼容问题。Monorepo 和 Polyrepo 的不同？前面说完之后，相信这里已经有了答案，这里再用对比…

前端权限开发——设计到实践
type: item
date: 2024-01-25T07:25:00+00:00
description: 做后台项目区别于做其它的项目，权限验证与安全性是非常重要的，可以说是一个后台项目一开始就必须考虑和搭建的基础核心功能。在后台管理系统中，实现权限控制可以采用多种方案：权限方案类型描述基于角色的访问控制（Role-Based Access Control，RBAC）是一种广泛采用的权限控制方案。系统中定义了不同的角色，每个角色具有一组权限，而用户被分配到一个或多个角色。通过控制用户角色的分配，可以实现对用户访问系统中不同功能和资源的权限控制。基于权限的访问控制（Permission-Based Access Control）这种方案将权限直接分配给用户，而不是通过角色来管理。每个用户都有自己的权限列表，控制用户对系统中各项功能和资源的访问。基于资源的访问控制（Resource-Based Access Control，RBAC）这种方案将权限控制与资源本身关联起来。系统中的每个资源都有自己的访问权限，用户通过被授予资源的访问权限来控制其对资源的操作。层次结构权限控制（Hierarchical Access Control）这种方案基于资源和操作的层次结构来进行权限控制。系统中的资源和操作被组织成层次结构，用户被授予访问某个层次及其子层次的权限。基于规则的访问控制（Rule-Based Access Control）这种方案使用预定义的规则来确定用户对系统中功能和资源的访问权限。规则可以基于用户属性、环境条件或其他因素进行定义。这里我选择了基于角色的访问控制（Role-Based Access Control，RBAC） 这是因为RBAC提供了一种灵活且易于管理的方式来控制用户对系统功能和资源的访问，也是目前最主流的前端权限方案选择。在RBAC中，系统中的功能和资源被组织成角色，而用户则被分配到不同的角色。每个角色都有一组权限，定义了该角色可以执行的操作和访问的资源。通过给用户分配适当的角色，可以实现对用户的权限控制。RBAC的好处之一是它简化了权限管理的复杂性。管理员只需管理角色和分配角色给用户，而不需要为每个用户单独定义权限。当需要对用户的权限进行修改时，只需调整其角色的权限即可。此外，RBAC还支持灵活的权限组合，允许创建具有不同权限组合的角色，以适应不同用户的需求。它也便于扩展，可以随着系统的发展和需求的变化而调整和添加角色。2.RBAC下的权限字段设计与管理模型1.用户权限授权是对用户身份认证的细化。可简单理解为访问控制，在用户身份认证通过后，系统对用户访问菜单或按钮进行控制。也就是说，该用户有身份进入系统了，但他不一定能访问系统里的所有菜单或按钮，而他只能访问管理员给他分配的权限菜单或按钮。主要包括：Permission（权限标识、权限字符串）：针对系统访问资源的权限标识，如：用户添加、用户修改、用户删除。Role （角色）：可以理解为权限组，也就是说角色下可以访问和点击哪些菜单、访问哪些权限标识。权限标识或权限字符串校验规则：权限字符串：指定权限串必须和菜单中的权限标识匹配才可访问权限字符串命名规范为：模块:功能:操作，例如：sys:user:edit使用冒号分隔，对授权资源进行分类，如 sys:user:edit 代表 系统模块:用户功能:编辑操作设定的功能指定的 权限字符串与当前用户的 权限字符串进行匹配，若匹配成功说明当前用户有该功能权限还可以使用简单的通配符，如 sys:user:*，建议省略为 sys:user（分离前端不能使用星号写法）举例1 sys:user 将于 sys:user 或 sys:user: 开头的所有权限字符串匹配成功举例2 sys 将于 sys 或 sys: 开头的所有权限字符串匹配成功 这种命名格式的好处有：可读性和可理解性 ：使用模块、功能和操作的格式可以直观地表达权限的含义。每个部分都有明确的作用，模块表示特定的模块或子系统，功能表示模块内的某个功能或页面，操作表示对功能进行的具体操作。通过这种格式，权限名称可以更容易地被开发人员、管理员和其他人员理解和解释。可扩展性和灵活性： 通过使用模块、功能和操作的格式，可以轻松地扩展和管理权限。每个模块、功能和操作都可以被单独定义和控制。当系统需要增加新的功能或操作时，可以根据需要添加新的权限字符串，而不需要修改现有的权限规则和代码。细粒度的权限控制： 这种格式支持细粒度的权限控制，可以针对特定的功能和操作进行权限管理。通过将权限名称拆分为模块、功能和操作，可以精确地定义哪些用户或角色具有访问或操作特定功能的权限。避免权限冲突： 使用模块、功能和操作的格式可以避免权限之间的冲突。不同模块、功能和操作的权限名称是唯一的，这样可以避免同名权限之间的混淆和冲突。2.权限管理模型关键数据模型如下：用户：登录账号、密码、角色角色：角色名称、角色权限…

rollup.js的个人理解
type: item
date: 2023-12-12T01:23:46+00:00
description: rollup也是一款静态资源打包工具。作用和webpack一样，但是比webpack轻量化。rollup和webpack的区别：webpack是一个静态资源打包器，从入口文件开始，webpack仅支持打包js，我们通过一个个loader打包其他不同类型的资源，通过插件实现额外的功能，最终将项目的所有文件编译成一个或多个文件输出出去。rollupjs也是静态资源打包成一个文件，rollup因为使用的前端模块化的方式是esm，于是有了tree shaking 特性。webpack由于要兼容commonjs，commonjs引入是全量引入，所以没有tree shakingwebpack 功能更加丰富，并且通过丰富的插件生态，如代码分割，适用于复杂场景和项目。rollup 更加轻便，它通过静态分析和Tree Shaking等技术，将代码模块按需打包，消除未使用的代码，以减小最终生成的包的体积。rollupjs 使用静态分析在编译时就确定依赖关系（所以在打包时会出现一下额外的依赖定义）webpack是运行时才进行依赖查找，所以在速度上会比较慢vite 是webpack的一个替代品。出现的原因是esm的出现和浏览器对esm的支持，使得在开发时运行不需要真正的编译，浏览器可以直接编译esm，所以在开发环境里，vite只是使用提供了开发服务器。生产环境下，vite 使用rollup进行代码编译。为了在生产环境中获得最佳的加载性能，最好还是将代码进行 tree-shaking、懒加载和 chunk 分割（以获得更好的缓存）。vite最大的特点是：冷启动热更新，生产环境用rollup，所以是tree shaking和静态分析。Tree ShakingTree Shaking技术其实就是代码按需打包技术，就是在打包过程中，只打包实际使用的代码，从而减少打包的体积。Tree Shaking的基础，我个人理解Tree Shaking的技术基础就是esm，正是esm的特性（具体如下），所以在打包过程中，可以做到区分代码是否用到。 Tree Shaking利用esm的特性：导入导出机制：ESM输出的是值的引用，这意味着如果模块内部的变量值发生变化，这些变化将反映到使用该变量的外部环境中。CommonJS输出的是值的拷贝，即使模块内部的值发生变化，外部环境中拷贝的值不会受到影响。依赖加载（解析）机制：ESM是编译时输出接口，而CommonJS是运行时加载。这意味着ESM在代码静态解析阶段就确定了模块的依赖关系，而CommonJS在运行时才解析模块依赖。ESM的import命令是异步的，而CommonJS的require()是同步的。这意味着ESM在加载模块时会分开模块的构建、实例化和执行，而CommonJS会同步加载整个模块Tree Shaking实现步骤（以Rollup的Tree Shaking实现方式举例）1. 识别依赖关系 ：在打包过程中，工具（如Rollup）会分析每个模块中的导入和导出语句，构建出一个模块依赖图。这个图记录了每个模块之间的依赖关系。2. 标记被使用的代码 ：通过静态分析技术，工具会遍历依赖图，并标记哪些变量、函数、类等被实际使用了。这些标记可以是通过变量引用、函数调用等方式进行识别。3. 剔除未使用的代码 ：根据标记结果，工具会将未被使用的代码从最终生成的文件中剔除掉。这些未使用的代码可能是整个模块、模块中的某些函数或类等。4. 优化输出结果 ：在剔除未使用代码后，工具会对输出结果进行进一步优化。它可能会进行变量重命名、函数内联等操作，以进一步减少文件大小和提高执行效率。Tree Shaking原理的核心在于静态分析和标记未使用代码。通过对模块依赖关系的分析，工具可以确定哪些代码是被实际使用的，哪些是未使用的。这种静态分析是在编译时进行的，因此可以在打包过程中进行优化，而不需要运行时的额外开销。需要注意的是，Tree Shaking只能消除那些在编译时可以确定未使用的代码。对于动态导入、条件导入等情况，工具可能无法准确判断哪些代码会被使用。因此，在使用Tree Shaking时，开发者需要注意编写可静态分析的代码，以确保最终生成的文件能够得到有效优化。由于是静态分析，所以我们在写代码的时候，需要注意自己的写法，简单来说，尽量的使用最小导入，例如，下面两个代码打包是不一样的：// 直接导入整个对象 import _ from 'lodash'; console.log(_.max([4, 2, 8, 6])) // 具名导入具体的函数 import { max } from 'lodash'; console.log(max([4, 2, 8, 6]))

前端工程化的思考
type: item
date: 2023-12-12T01:18:00+00:00
description: 前端工程化定义前端工程化。是一种将软件工程的方法和思想应用于前端开发的实践，它旨在提高开发效率、降低开发成本、保证代码质量，这包括使用构建工具、实行模块化和组件化、自动化和持续集成等技术。前端工程化关注于开发流程的规范化、标准化，以及通过工具和框架解决前端开发和前后端协作中的问题。例如，使用脚手架工具、代码规范和格式化、热更新和Mock数据、自动化测试和持续部署等都是前端工程化的体现。模块化。指的是将复杂的程序或系统拆分成多个独立的模块，每个模块负责特定的功能，这些模块可以单独开发、测试和维护，模块化有助于提高代码的可维护性、复用性和管理性。在前端开发中，模块化通过将代码拆分为小的、独立的文件来实现，这些文件通过统一的拼装和加载来协同工作。JavaScript的模块化规范，如CommonJS，定义了模块的作用域和加载机制，有助于避免全局作用域的污染和提高代码的复用率。组件化。是模块化的一种表现形式，它专注于用户界面的拆分和维护。组件化将页面结构、样式和行为分离成独立的组件，每个组件都有自己的工程目录和所需资源，组件之间可以自由组合，形成完整的页面。这种方法的优点在于提高代码的复用性和维护性，同时也方便了多人协作和项目的扩展。总的来说，前端工程化、模块化和组件化共同促进了前端开发的效率和质量，它们是现代前端开发中不可或缺的部分。前端工程化是指将前端开发中的项目管理、构建、测试、部署等环节进行规范化和自动化，以提高开发效率、代码质量和团队协作能力的一种开发方式。具体来说，前端工程化涉及以下几个主要方面：项目架构：对项目的文件组织结构、模块划分、代码规范等进行规范化。良好的项目架构可以提高代码的可维护性和可扩展性。版本控制：使用版本控制系统（如Git）对代码进行管理，实现多人协作、版本回退、分支管理等功能，保证代码的版本和历史可追溯。自动化构建：使用构建工具（如Webpack、Gulp）将源码编译、压缩、合并、打包等操作自动化处理，以生成可部署或上线的最终代码。组件化与模块化：通过将页面拆分成一个个独立的组件和模块，可以更加灵活地组合和复用代码，提升开发效率和代码可维护性。组件化是在设计层面上，对于UI的拆分；而模块化是将一个大文件拆分成相互依赖的小文件，再进行统一的拼装和加载。自动化测试：自动化测试可以大大提升测试效率，减少人为错误。前后端分离与全栈工程化：前后端分离已经成为了现代Web开发的主流架构，前端和后端可以独立开发、独立部署、独立测试，大大提升了开发效率和产品质量。同时，全栈工程化的思想也在逐渐普及，即前后端使用统一的工程化标准和流程，进一步提升团队协作效率。前端工程化的目标是提升团队协作效率、提高代码质量、降低维护成本，并使前端开发更加规范和可持续。同时，它也能够适应快速迭代、多平台适配的现代前端开发需求。