如何从0到1构建基于自身业务的前端工具库

描述

前言

在实际项目开发中无论 M 端、PC 端,或多或少都有一个 utils 文件目录去管理项目中用到的一些常用的工具方法,比如:时间处理、价格处理、解析 url 参数、加载脚本等,其中很多是重复、基础、或基于某种业务场景的工具,存在项目间冗余的痛点以及工具方法规范不统一的问题。

在实际开发过程中,经常使用一些开源工具库,如 lodash,以方便、快捷的进行项目开发。但是当 npm 上没有自己中意或符合自身业务的工具时,我们不得不自己动手,此时拥有自己的、基于业务的工具库就显得尤为重要。

我们所熟知的 Vue、React 等诸多知名前端框架,或公司提供的一些类库,它们是如何开发、构建、打包出来的,本文将带领你了解到如何从 0 到 1 构建基于自身业务的前端工具库。

构建工具库主流方案

1. WEBPACK

webpack 提供了构建和打包不同模块化规则的库,只是需要自己去搭建开发底层架构。

vue-cli,基于 webpack , vue-cli 脚手架工具可以快速初始化一个 vue 应用,它也可以初始化一个构建库。

2. ROLLUP

rollup 是一个专门针对 JavaScript 模块打包器,可以将应用或库的小块代码编译成更复杂的功能代码。

Vue、React 等许多流行前端框架的构建和打包都能看到 rollup 的身影。

为什么采用 ROLLUP 而不是 WEBPACK

webpack 主要职能是开发应用,而 rollup 主要针对的就是 js 库的开发,如果你要开发 js 库,那 webpack 的繁琐配置和打包后的文件体积就不太适用了,通过 webpack 打包构建出来的源代码增加了很多工具函数以外的模块依赖代码。

rollup 只是把业务代码转码成目标 js ,小巧且轻便。rollup 对于代码的 Tree-shaking 和 ES6 模块有着算法优势上的支持,如果只想构建一个简单的库,并且是基于 ES6 开发的,加上其简洁的 API,rollup 得到更多开发者的青睐。

工具库底层架构设计

构建工具库底层架构大概需要哪些功能的支持: 框架

架构依赖需知

在对底层架构设计的基础上,首先需要把用到的依赖库简单熟悉一下:

rollup 全家桶

•  rollup(工具库打包构建核心包) •  rollup-plugin-livereload(rollup 插件,热更新,方便本地 debugger 开发) •  rollup-plugin-serve(rollup 插件,本地服务代理,方便在本地 html 中调试工具) •  rollup-plugin-terser(rollup 插件,代码压缩混淆) •  rollup-plugin-visualizer(rollup 插件,可视化并分析 Rollup bundle,以查看模块占用) •  @rollup/plugin-babel(rollup 插件,rollup 的 babel 插件,ES6 转 ES5) •  @rollup/plugin-commonjs(rollup 插件,用来将 CommonJS 模块转换为 ES6,这样它们就可以包含在 Rollup 包中) •  @rollup/plugin-json(rollup 插件,它将.json 文件转换为 ES6 模块) •  @rollup/plugin-node-resolve(rollup 插件,它使用节点解析算法定位模块,用于在节点模块中使用第三方 node_modules 包) •  @rollup/plugin-typescript(rollup 插件,对 typescript 的支持,将 typescript 进行 tsc 转为 js)

typescript 相关

•  typescript(使用 ts 开发工具库) •  tslib(TypeScript 的运行库,它包含了 TypeScript 所有的帮助函数) •  @typescript-eslint/eslint-plugin(TypeScript 的 eslint 插件,约束 ts 书写规范) •  @typescript-eslint/parser(ESLint 解析器,它利用 TypeScript ESTree 来允许 ESLint 检测 TypeScript 源代码)

文档相关

•  typedoc(TypeScript 项目的文档生成器) •  gulp(使用 gulp 构建文档系统) •  gulp-typedoc(Gulp 插件来执行 TypeDoc 工具) •  browser-sync(文档系统热更新)

单元测试相关

•  jest(一款优雅、简洁的 JavaScript 测试框架) •  @types/jest(Jest 的类型定义) •  ts-jest(一个支持源映射的 Jest 转换器,允许您使用 Jest 来测试用 TypeScript 编写的项目) •  @babel/preset-typescript(TypeScript 的 Babel 预设)

其他依赖

•  eslint(代码规范约束) •  @babel/core(@rollup/plugin-babel 依赖的 babel 解析插件) •  @babel/plugin-transform-runtime(babel 转译依赖) •  @babel/preset-env(babel 转译依赖) •  chalk(控制台字符样式) •  rimraf(UNIX 命令 rm -rf 用于 node) •  cross-env(跨平台设置 node 环境变量)

底层架构搭建

1. 初始化项目

新建一个文件夹 utils-demo,执行 npm init,过程会询问构建项目的基本信息,按需填写即可:

npm init

 

2. 组织工具库业务开发 SRC 目录结构

创建工具库业务开发 src 文件目录,明确怎样规划工具库包,里面放置的是工具库开发需要的业务代码: 框架

3. 安装项目依赖

要对 typescript 代码进行解析支持需要安装对 ts 支持的依赖,以及对开发的工具的一些依赖包:

yarn add typescript tslib rollup rollup-plugin-livereload rollup-plugin-serve rollup-plugin-terser rollup-plugin-visualizer 
@rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-typescript 
@babel/core @babel/plugin-transform-runtime @babel/preset-env rimraf lodash chalk@^4.1.2 -D
这里遇到一个坑,关于最新 chalk5.0.0 不支持在 nodejs 中 require () 导入,所以锁定包版本 chalk@^4.1.2 要对 typescript 进行解析和编译还需要配置 tsconfig.json,该文件中指定了用来编译这个项目的根文件和编译选项,在项目根目录,使用 tsc --init 命令快速生成 tsconfig.json 文件(前提全局安装 typescript)
npm i typescript -g
tsc --init
初始化 tsconfig 完成之后,根目录自动生成 tsconfig.json 文件,需要对其进行简单的配置,以适用于 ts 项目,其中具体含义可以参考 tsconfig.json 官网

 

4. 组织项目打包构建 SCRIPTS 目录结构

1) 根目录创建项目打包构建 scripts 脚本文件目录,里面放置的是有关于项目打包构建需要的文件: 框架 生成 rollup 配置项函数核心代码:

const moduleName = camelCase(name) // 当format为iife和umd时必须提供,将作为全局变量挂在window下:window.moduleName=...
const banner = generateBanner() // 包说明文案
// 生成rollup配置文件函数
const generateConfigs = (options) => {
  const { input, outputFile } = options
  console.log(chalk.greenBright(`获取打包入口:${input}`))
  const result = []
  const pushPlugins = ({ format, plugins, ext }) => {
    result.push({
      input, // 打包入口文件
      external: [], // 如果打包出来的文件有项目依赖,可以在这里配置是否将项目依赖一起打到包里面还是作为外部依赖
      // 打包出口文件
      output: {
        file: `${outputFile}${ext}`, // 出口文件名称
        sourcemap: true, // // 是否生成sourcemap
        format, // 打包的模块化格式
        name: moduleName, // 当format为iife和umd时必须提供,将作为全局变量挂在window下:window.moduleName=...
        exports: 'named' /** Disable warning for default imports */,
        banner, // 打包出来的文件在最顶部的说明文案
        globals: {} // 如果external设置了打包忽略的项目依赖,在此配置,项目依赖的全局变量
      },
      plugins // rollup插件
    })
  }
  buildType.forEach(({ format, ext }) => {
    let plugins = [...defaultPlugins]
    // 生产环境加入包分析以及代码压缩
    plugins = [
      ...plugins,
      visualizer({
        gzipSize: true,
        brotliSize: true
      }),
      terser()
    ]

    pushPlugins({ format, plugins, ext })
  })
return result
}


2) rollup 在打包构建的过程中需要进行 babel 的转译,需要在根目录添加.babelrc 文件告知 babel:
{
  "presets": [
    [
      "@babel/preset-env"
    ]
  ],
  "plugins": ["@babel/plugin-transform-runtime"]
}

 

3) 此时距离打包构建工具库只差一步之遥,配置打包脚本命令,在 package.json 中配置命令:

 

"scripts": {
    "build": "rimraf lib && rollup -c ./scripts/rollup.config.js" // rollup打包
 },

 

4) 执行 yarn build,根目录会构建出一个 lib 文件夹,里面有打包构建的文件,还多了一个 stats.html,这个是可视化并分析 Rollup bundle,用来查看工具模块占用空间:

框架 架构搭建优化 项目搭建到这里,不知机智的你能否发现问题: 1) 只要添加了一个工具,就要在入口文件导出需要打包构建的工具,在多人开发提交代码的时候将引来冲突的产生: 框架 2) 使用工具库的时候,按需引用的颗粒度太细了,不能满足一些要求颗粒度粗的朋友,比如: • 我想使用该包里面 date 相关工具,要这样吗?

import { dateA, dateB, dateC } from "utils-demo"

 

能不能这样?

 

import { date } from "utils-demo"
date.dateA()
date.dateB()
date.dateC()

• 在一些使用 script 脚本引入的场景下,就仅仅需要 date 相关的工具,要这样吗?

                    
                
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分