阅读 7926

如何在不同项目中共用前端资源,从此不加班

作者/Function(前端时空)

公众号「前端时空」每日一题活动 回复「1」看面试题 | 回复「2」看答案

文章已同步发表于

微信公众号「前端时空」语雀知乎

前言

随着公司前端项目的增多, 大家会发现各个项目中很多资源都是是大同小异的,这就引发了一个话题,如何跨项目共用前端资源, 这里的资源泛指前端涉及到的所有静态资源, 常见的有 HTML/CSS/JS/图片等等.

所谓共用前端资源, 就是将公共的前端资源提取出来, 例如公共样式/公共逻辑/公共组件/公共图片资源等等, 让多个项目来引用, 避免复制多份, 避免重复开发, 统一管理和维护。只要更新公共资源,其他引用的项目就可以同步更新,提升开发效率,降低开发成本。

自研方案 npm 和 Webpack

想共用前端资源, 必须先将公用的前端资源以包的形式统一地管理起来, 形成一个公共仓库, 在项目中声明依赖的前端资源包, 通过工具来下载依赖的具体资源文件。

开发时使用模块打包器分析出具体的依赖文件, 打包出项目依赖的所有前端资源。

因此我们需要一个包管理器和模块打包器, 即可实现梦寐以求地共用前端资源。

  • 包管理器: npm

npm is the package manager for JavaScript manage dependencies in your projects

管理项目级别的依赖, 必要时搭建一套 npm 私服

  • 模块打包器: Webpack

Webpack is a module bundler for modern JavaScript applications it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles - often only one - to be loaded by the browser.

构建工具分析并打包依赖, 现在你可以放心大胆地修改和删除项目历史遗留的静态资源文件了

  • 任何资源都可以视为一种依赖, 在构建时分析出资源的引用关系
  • 如果某个资源是僵尸资源, 删除后不会引发构建失败, 因为已经没有任何文件引用(依赖)它了
  • 在没有构建工具分析依赖的年代,你只能通过全局搜索的方式来确定一个文件还有没有用,但可能还是没有办法下达删除的决定(万一其他项目引用了呢?)

接下来, 共用前端资源的关键就是将公共的模块发布到 npm 里面, 然后就是在各个项目声明依赖实际使用了。

实际使用的方式就落在了: 如何通过 Webpack 在 HTML/CSS/JS 文件中引用 npm 模块(即 node_modules 文件夹), 或者是 npm 模块中的文件

HTML:

<!-- 引用 npm 模块 ionicons 中的文件 -->
<img src="~ionicons/dist/svg/ios-sunny.svg" width="50" height="50">
复制代码

CSS:

/* 导入 npm 模块: normalize.css, 会自动去找 main 文件 */
@import url(~normalize.css);

.test-npm-res {
    /* 引用 npm 模块 ionicons 中的文件 */
    background-image: url(~ionicons/dist/svg/ios-partly-sunny-outline.svg);
}
复制代码

JS:

// 导入 npm 模块 ionicons 中的文件
import svg from 'ionicons/dist/svg/ios-sunny-outline.svg';
复制代码

示例

我们只需要关注使用的模块, 不再需要关注模块的依赖了

  • 共用静态资源文件: 在各个项目中引用公共的公司 Logo 图片

将公共静态资源在 npm 上发布为一个 company-common-res 的模块包

company-common-res/
├── src/
|   |── logo.psd
|   └── ...
|
├── dist/
|   |── logo.png
|   └── ...
|
└── package.json
复制代码

在项目的 package.json 中声明依赖这个模块

"dependencies": {
  "company-common-res": "^1.0.0",
}
复制代码

然后就是在 HTML/CSS/JS 文件中引用这个静态资源了, 以 HTML 文件中为例

<img src="https://user-gold-cdn.xitu.io/2017/12/21/1607716e35b27686" width="50" height="50">
复制代码
  • 共用 CSS 组件: 在各个项目中引用公共的 CSS 样式

将公共的 CSS 基础样式在 npm 上发布为一个 company-component-base 的模块包, 在项目的 package.json 中声明依赖这个模块   company-component-base模块的 package.json 应该声明 main 为组件的 CSS 文件 "main": "company-component-base.css"

在项目中使用这个组件, 以 CSS 文件中为例

@import url(~company-component-base);

将公共的 CSS 组件在 npm 上发布为一个 company-component-button 的模块包

@import url(~company-component-button);

  • 公共 JS 模块(纯逻辑模块, 不包含样式): 在各个项目中引用公共的 JS 工具方法

将公共的 JS 工具方法在 npm 上发布为一个 company-util 的模块包, 在项目的 package.json 中声明依赖这个模块

import util from 'company-util';
util.log('test');
复制代码

+公共 JS 组件(包含样式): 在各个项目中引用公共的 toast 组件

将 toast 组件在 npm 上发布为一个 company-component-toast 的模块包, 在项目的 package.json 中声明依赖这个模块

import Toast from 'company-component-toast';

new Toast({
    content: '提示内容'
}).show();
复制代码

技术演进

随着时间的迁移,技术不断演进,我找到了一种方案————组件池

组件池

你想问什么是组件池?组件池是一个复用的组件的池子,它提供的一套上传、共享的能力。可以理解为在可视化编辑的基础上提供一个快速搬运使用代码片段的能力。任何组件都能在组件池中共存, 而且内置可视化编辑效果的 editor。组件池的重点是像 codeSandbox/codePen 然后再提供某种快速拿来使用的能力, 比如结合 vscode 的 snipshot, 或者简单点直接把代码复制张贴过来。

成本

然而实现一个上述的组件池,也就是要实现一个 codeSandbox (codeSandbox/codePen ), 成本会很高,并且内置可视化的编辑器是标配,以及便捷的共享复用能力,都需要攻克难点。于是便去寻找开源解决方案,苦苦寻觅之中,Bit 让我眼前一亮。

推荐方案 Bit

Github: github.com/teambit/bit

Bit 是一个开放源码的 cli 工具,用于跨项目和存储库的隔离组件进行协作。 使用 Bit 将分散的组件从设计库或项目分发到独立的可重用包中,并在应用程序中使用它。 您可以设置自己的服务器来进行组件协作,也可以使用 bit.dev 云托管进行私有和公共组件共享。

Bit 简化了 UI 组件上的协作过程。团队成员可以共享,维护和同步来自不同项目的隔离组件。

Bit 能帮助团队:

  • 提高代码可重用性
  • 提高设计和开发效率
  • 保持 UI 和 UX 的一致性
  • 增加项目的稳定性

主要特征:

  • 从现有的库或项目中提取要直接共享的组件。
  • 通过与项目的其余部分分开构建和测试每个组件,验证组件的独立性。
  • 从任何使用共享组件的应用程序中更改其源代码。
  • 在本地修改的基础上获取组件中已发布的更改。
  • 直接从使用应用程序中回馈对组件所做的更改。
  • 自动将每个组件包装为 npm 软件包。
  • 分发离散组件,而不是单个大型软件包。
  • 根据组件依赖性的变化自动进行组件版本控制。
  • 与领先的框架和工具一起使用:React,Vue,Angular,Mocha,Jest。
  • 与 Git,NPM 和 Yarn 一起使用。

Bit 可以在 Javascript 和 Javascript 框架使用

框架

下面将教您如何使用 Bit

Bit 的使用

安装 Bit

如果您使用的是 node 8.12 及更高版本,则可以使用 NPM 或 Yarn 安装 Bit:

npm install bit-bin -g

初始化 Bit 工作区

要共享项目中的组件,应在该项目中初始化 Bit:

bit init

Bit 组件应该很小,并且只能保存组件的相关文件。但是,通常是从您正在使用的框架(例如 React 或 Vue)中导入组件,或者它们包含特定于项目的依赖项(例如Storybook)。为了确保在 Bit 组件中排除那些依赖关系,我们需要将它们配置为peerDependencies。

以下示例适用于 React,但您应将类似的方法应用于任何其他框架或其他工具和库。请查看一下您使用框架的配置规则,以获取更多信息。

为此,您需要配置您的位工作区。在package.json文件中添加与此类似的部分:

"peerDependencies": {
 "react": ">=16.9.0",
 "react-dom": ">=16.9.0",
 "styles-components": ">=4.0.0",
 "@storybook/react": ">=5.2.0"
}
复制代码

跟踪 Track

要开始跟踪 Bit 中的组件,请使用add命令。组件具有其文件后,Bit可以识别并验证该组件的所有依赖项是否存在,并跟踪所有文件。Bit还可以将组件与实用程序(例如编译器或测试器)相关联,并开始隔离地构建和测试组件。

新增文件

开始跟踪项目中的组件。明确定义和隔离的组件是很好的跟踪对象。 使用bit add命令跟踪组件:

bit add src/components/my-component.ts --id my-component

您可以一次跟踪多个组件:

bit add src/components/*

这将跟踪src/components目录中的所有组件。每个组件将位于以其组件ID命名的目录中。 您还可以通过附加标志来将测试文件作为组件的一部分进行跟踪--tests。Bit可以隔离运行这些测试并显示结果。

使用 bit status 验证组件被跟踪,并且没有文件丢失。

添加编译器

Bit 组件可以通过以下两种方式之一在其他项目中使用:

  • 导入源代码并将其嵌入到使用项目中。
  • 安装项目将其作为 NPM 软件包使用的构建构件(例如dist目录)。

要构建组件并创建构建工件,您需要为您从项目中共享的组件定义一个编译器。编译器本身也是一个组件,因此我们使用 bit import 命令将其导入到我们的项目中:

$ bit import bit.envs/compilers/babel --compiler
the following component environments were installed
- bit.envs/compilers/babel@0.0.7
复制代码

添加测试

如果您跟踪组件的测试文件,则可以定义 Bit 将用来运行它们的测试框架。像编译器一样,Bit 测试是作为组件提供的工具:

$ bit import bit.envs/testers/mocha --tester
the following component environments were installed
- bit.envs/testers/mocha@0.0.7
复制代码

发布

当准备好与他人共享某个组件时,开发人员会使用遵循约定的版本号标记该组件。 Bit 存储组件源代码的快照,使它可以在进行任何更改时通知使用者。 开发人员可以将组件的标记版本导出到中央服务器。集中式服务器可以是自有的,也可以将bit.dev 云服务用作集中式服务器。

标签组件的版本

要为组件设置版本,请使用 bit tag 命令。 Bit 锁定组件文件及其依赖关系图的状态。现在,已标记的版本是不可变的(无法更改)。 在标记组件时,Bit 首先运行组件的构建和测试任务。 您可以使用该 --all 标志标记工作空间中所有更改的组件。

$ bit tag --all 1.0.0
3 components tagged | 3 added, 0 changed, 0 auto-tagged
added components: components/button@1.0.0, components/login@1.0.0, components/logo@1.0.0
复制代码

创建远程范围

要在不同项目之间共享组件,您需要将组件存储在远程范围内。

要设置自己的 Bit 服务器,请按照此处的说明进行操作。

或者,您可以使用 bit.dev 云托管来共享组件。通过 bit.dev 服务器共享组件。

  • 在 bit.dev 上创建一个帐户
  • 按照 bit.dev 上的步骤创建集合。在新创建的集合页面上,您可以看到导出命令,您稍后将使用该命令来导出组件。

对您自己的服务器或 bit.dev 运行位登录(如果您已经登录浏览器,位登录将自动登录到该帐户)。

$ bit login
Your browser has been opened to visit: http://bit.dev/bit-login?redirect_uri=http://localhost:8085...
复制代码

您现在有了一个收藏夹。在 bit.dev 上,您可以看到导出命令,稍后将使用该命令将组件导出到该集合。

导出组件

使用bit export命令将组件从工作区发布到 bit.dev。

$ bit export user-name.collection-name
exported 3 components to collection user-name.collection-name
复制代码

转到您的 bit.dev 集合。所有组件均已导出。尝试为您的组件创建并保存示例,Bit 也会在集合页面中显示为预览。

安装组件

导出后,该组件现在可供其他开发人员以以下两种方式之一使用:安装或导入。

现在,您可以使用 NPM 或 Yarn 安装组件。与其他NPM软件包一样,该组件将与构建工件(例如 dist 文件夹)一起安装。已安装的组件位于 node_modules 文件夹中。

如果使用 NPM 或 Yarn,则 NPM 应该将 Bit 配置为作用域注册表(Bit 登录时 Bit 会自动配置它):

npm config set @bit:registry https://node.bit.dev

然后,使用组件页面上的 install 命令,使用您最喜欢的软件包管理器来安装组件。范例:

npm i @bit/mui-org.material-ui.button

导入和修改

您可能需要修改组件源代码(例如,修复错误或更改功能)。为此,您需要将组件导入项目并应用更改。

现在可以对已更新的组件进行标记并重新导出,以便该组件的其他使用者可以获取更新。

导入组件

因为 Bit 隔离了组件并将它们与存储库分离,所以您可以从代码库中的任何存储库开发Bit组件。 要从使用库中开发组件,请使用以下bit import命令:

bit import mui-org.material-ui/button 注意:如果更改是临时的,并且您想恢复使用中的组件 node_modules,则可以使用该eject命令从本地工作区中删除组件,并将其与 NPM 客户端一起安装。

发布组件更改

对导入的组件所做的更改可以在集合中进行更新,并可以在整个项目中使用。 完成更改后,可以将它们作为组件中组件的新版本进行更新(前提是您有权更新集合)。或者,可以将更改后的组件导出为新组件。 使用集合中的新版本更新组件时,每个包含该组件的存储库都可以获取更改。

合并

使用 Bit,在项目中导入和修改组件时,它仍会接收对原始组件所做的修改。可以在原始项目以及导入组件的任何项目中获取更新。这有助于团队在开发来自不同项目的组件时同步更改。

bit import mui-org.material-ui/button
bit checkout mui-org.material-ui/button --interactive-merge
复制代码

精彩文章

理想主义团队的开源作品之Chameleon跨端框架
React 中必会的 10 个概念
一道面试题引发关于 js 隐式转换的思考
前端首屏耗时测量方法
一分钟理解 JavaScript 发布订阅模式
前端响应式你了解多少?


喜欢我们的小伙伴
请点击点赞、分享、评论哟
关注我们的公众号,学习知识不迷路

关注下面的标签,发现更多相似文章
评论