当前位置:   article > 正文

打造一个类似于lodash的前端工具库_做一个和lodash-es一样的工具库

做一个和lodash-es一样的工具库

 

一、分析借鉴目前最主流的前端工具库

我分析了github上多个前端工具库的设计,以lodash为例说明:

lodash的工程,有master、npm、npm-package、amd分支,以及 多种类型的tag:

  • 4.17.10(umd)

  • 4.17.10-npm

  • 4.17.10-es

  • 4.17.10-amd

这 4个分支 + 4个tag 的代码甚至工程结构,都不太一样。

我目前还看不明白它这么多套代码,是分开维护的,还是只维护一套,其他都是自动生成的?

因为所有8个分支的配置我都检查过了,并没有发现自动生成多份代码的相关配置。

而且lodash工程里面并没有babel的配置,难道lodash各个版本的代码是分开维护的?

 

本来想模仿lodash的工程脚手架,无奈看了半天看不懂。但是它的功能我基本清楚了:

1、umd模块,分为 lodash-core.js 和 lodash.js 、lodash-fp.js 三部分,提供了 未压缩包和压缩包(貌似没有看到source map)。

  lodash-fp 即 (Functional Programming)函数式编程,对于_.map等部分方法,lodash提供了FP版本

2、npm模块(也是CommonJS版),有各个主功能模块(比如array),都是require和module.export形式,除了lodash.js提供了min压缩版,其他都是源码无压缩。

3、AMD版,全部都是源码无压缩,有主功能模块(比如array),都是define引入/导出模式,但是没有lodash.js统一入口模块。

4、es模块,全部都是源码无压缩,主功能模块全部提供了 default引入形式(例如array.default.js)以便支持 import array from 'lodash/array'。

5、npm模块,分成很多子项目,每一个函数都可以单独install。

 

除了lodash,我还分析了vue和react的工程构建方式,并学习了rollup、jest等。

 

二、设计自己的前端工具库

 

我想达到的目的:

1、要支持 es6、node-cjs 和 浏览器 script直接引入,暂时不单独考虑支持amd;

2、只维护一套代码,其他均有工具自动生成;

3、浏览器版本的,支持source map,其他版本都是源码形式提供;

4、cjs、es6版本,支持按函数和主功能模块(例如array、date)引入,es6版本还提供对import xxx 这种形式的支持;

5、浏览器版本的,暂时不分模块,只能支持全部引入,后面根据情况可以提供core等精简版本。

 

关于源码的书写和维护:

目前大多数工具库,都是用的es6语法,我看vue源码是用的带type类型的es6(好像叫flow),lodash源码好像是es6(master分支),而react用的好像也是自家的flow,只有谷歌的angular2用的typescript。

所以我考虑采用 es6来编写,但不排除以后换成ts。

 

具体做法:

 

使用es6语法来编写工具类,并把源代码原原本本提供出去,同时生成一份umd格式的,包含源码、压缩包和source map。

整个target(dist)内容示例如下:

// 所有函数

toMapKey.js

toMapValue.js

...

collection.js // 主功能模块

collection.default.js // xxx.default.js用于支持es6的直接import

...

zollty-util.esm.js // 主模块es源码,相当于 index.js、main.js

zollty-util.esm.default.js // xxx.default.js用于支持es6的直接import xxx from 'xxx.js',并且用它来生成umd版本

zollty-util.js // umd版本的源码,根据zollty-util.esm.default.js自动生成

zollty-util.min.js // umd版本压缩后的代码

zollty-util.min.map // umd版本压缩代码的source map

 

xxx.default.js 说明

以collection.js为例:

collection.default.js代码如下:

import toMapKey from './toMapKey.js';

import toMapValue from './toMapValue.js';

// 支持单个引入 import { toMapKey, toMapValue } from 'collection.default'

// 也可以像这样全部引入 import * as coll from 'collection.default';

export default {

toMapKey,

toMapValue,

}

collection.js代码如下:

// 支持单个引入 import { toMapKey, toMapValue } from 'collection'

export { default as toMapKey } from './toMapKey.js';

export { default as toMapValue } from './toMapValue.js';

 

// 支持default(默认)引入 import coll from 'collection'

export { default } from './collection.default.js';

即 collection.default.js 只是供 collection.js 来引入的,其作用是为它提供 export default 的功能,以支持能直接 import coll from 'collection'。

 

上面是target(dist)的目录,那么源码src目录应该是怎样呢?

维护源码的时候,应该分模块,比如 集合相关的工具函数,放到 src/collection/ 目录下

src / 

|--collection / 

|  |--- toMapValue.js

|  |--- toMapKey.js

|  |---  ......

|--array / 

|-- .....

|--zollty-util.js

|_______________

构建的时候,将所有模块都拷贝到target(dist)目录下,同时自动生成各模块的主module和总module。

 

关于构建工具

经我广泛的研究,结论如下:

1、应用类的工程,用webpack来打包;

2、工具类的工程,用rollup来打包,例如vue和react,都是用的rollup来打包。

 

所以,这个工程,决定用rollup来打包,而不是webpack。

rollup打包出来,代码更干净,就像自己写的代码一样,而webpack打包出来,会添加很多其他的代码。

 

其他功能

1、单元测试

使用jest来做单元测试。

 

2、持续集成

使用 travis。

 

git代码地址:https://github.com/zollty-org/zollty-util.js

npm仓库地址:https://www.npmjs.com/package/@zollty/zollty-util

 

三、架构和技术说明

 

技术列表如下:

 

核心技术:

babel

rollup

jest

terser

eslint

 

辅助技术

cross-env

commitlint // 检查git commit,要求其符合规范

semantic-release

husky // 拦截不符合规范的git commit和push

travis-deploy-once

 

codecov

jshint

editorconfig

browserslist

 

技术说明:

 

使用rollup构建

配置在根目录下面的 rollup.config.js 

 

在使用 rollup 构建之前,会先准备打包文件,会执行node build/prepare

build/prepare.js的基本作用是 把 src 下面的文件拷贝 到 tmp 目录,同时生成 子模块的js,例如 zollty-util.esm.js、collection.js、collection.default.js

同时,会修正js中import的路径。

 

需要说明的是,rollup.config.js配置中的

globals(),

builtins(),

localResolve(),

resolve()

commonjs()

这些应该暂时还没用到。

export出的配置,是一个数组,不同的input文件,输出配置不一样,

例如 对于 tmp/main.js (实际上为zollty-util.esm.js)文件,输出了 umd、iife、cjs 三种格式,

同时,在zollty-util.esm.js的基础上,再次转换成  zollty-util.es.js (es6 module的es5语法的文件),之所以要转换成 es5语法,其初衷是想它被其他模块引入时,不需要babel转换也能直接使用,zollty-util.es.js会被当做本js库的package.json的main入口。(其实,我也不确定这样做到底有多少意义),具体参见这篇文章的描述:https://loveky.github.io/2018/02/26/tree-shaking-and-pkg.module/

 

其配置文档,参见:

深入学习rollup来进行打包

JS打包工具rollup——完全入门指南

使用模块化工具打包自己开发的JS库

https://rollupjs.org/guide/zh#npm-packages

https://github.com/rollup/rollup

 

使用terser压缩es6语法的 js

terser是uglify-es6的增强版,因为uglify不支持es6,而uglify-es6又停止更新了,故推出了terser

terser支持和rollup集成,但是我在rollup打包过程不包含js压缩,为更灵活的控制 js压缩,我单独写了个脚本 ,执行node build/minify来处理压缩。

 

我是用的terser默认的配置,只是添加了 sourcemap的生成。

 

terser使用文档如下:

https://github.com/terser-js/terser

 

babel 及 browserslist 配置

rollup构建时,引入了  rollup-plugin-babel 插件,会调用 babel 对js进行处理。

babel的配置文件为:.babelrc.js

我使用 的是 babel 7(@babel/core@7.2.0),其配置和 babel 6有很大的不一样。

目前,只配置了一个babel-preset-env,其说明参见:

https://babeljs.io/docs/en/babel-preset-env/#how-it-works

https://www.babeljs.cn/docs/setup#installation

另外,babel 默认使用 .browserslistrc 的配置,其内容如下:

> 5%

current node

not dead

等价于 在package.json中配置 [ "browserslist": "> 5%, current node, not dead" ]

对于browserslist的使用,参见其说明文档:https://github.com/browserslist/browserslist

 

jest 单元测试配置

配置放在 jest.config.js 文件中

主要设置了 "verbose": true 以报告每个测试的执行情况,显示执行时间。

其配置文档参见:https://jestjs.io/docs/zh-Hans/configuration

 

注意,jest 需要依赖 babel-jest,要依赖babel 6,需要安装 babel 6 和 babel 7的桥接。

babel-jest,文档:https://www.npmjs.com/package/babel-jest

文档中说,如果使用babel 7的话,需要安装babel 6~7的桥接版本'babel-core@^7.0.0-bridge'

 

单元测试的代码,统一放在了 __test__ 目录下,这个是 jest 默认扫描的目录之一(该目录下面的js文件都会执行),无需配置。

 

注意,jest 测试代码,我也用的是 es6语法。

 

IDE(VS Code)使用 eslint 插件检查和自动更正 js 代码

 

我在 vs code 编辑器中 安装了 eslint 插件,

并在IDE中配置了如下(setting.json):

{

  "terminal.integrated.shell.windows""D:\\C\\Program Files\\Git\\bin\\bash.exe",

  "eslint.autoFixOnSave"true,

  "eslint.options": {

    "plugins": ["html"],

    "extensions": [".js"".vue"]

  },

  "eslint.validate": [

    "javascript",

    "javascriptreact",

    {

      "language""vue",

      "autoFix"true

    },

    {

      "language""html",

      "autoFix"true

    }

  ],

  "vue-peek.supportedLanguages": ["vue"],

  "vue-peek.targetFileExtensions": [".vue"".js"],

 

  // 开启保存时自动format,一定要配合下面的format组件一起使用

  "editor.formatOnSave"true,

    // 使用prettier来format代码,相关配置如下:

  "prettier.singleQuote"true,

  "prettier.semi"false,

  "vetur.format.defaultFormatterOptions": {

    "prettier": {

      "singleQuote"true,

      "semi"false

    }

  },

  // 使用js-beautify替换prettier

  // "vetur.format.defaultFormatter.html": "js-beautify-html",

    "explorer.autoReveal"false,

  "workbench.editor.enablePreview"false,

  "terminal.integrated.scrollback": 10000,

  "javascript.updateImportsOnFileMove.enabled""always",

  "files.associations": {

    ".jshintrc""jsonc",

    ".eslintrc""jsonc"

  }

}

注意到上面的,files.associations 这个配置是为了 在json中支持注释。

 

另外,我配置了 .eslintignore,用来排除 部分目录和代码,不进行eslint 校验。

 

另外,我安装了jshint插件(本工程无需这个插件),需要在工程根目录 新建 .jshintrc 文件,内容如下;

{

 "undef": true,

 "unused": true,

 "esversion": 6,

 "asi": true

}

jshint详细配置参见:https://jshint.com/docs/options/

 

命令行使用 eslint 检查 js 代码

运行 eslint --ext .js ./src 即可检查 js 源码是否符合规范。

eslint的配置文件为 .eslintrc,内容如下:

{

  "extends": "airbnb-base",

  "env": {

    "jest": true,

    "browser": true,

    "node": true,

    "es6": true

  },

  "rules": {

    "semi": [0, "never"],

    "semi-spacing": [2, {

      "before": false,

      "after": true

    }]

  }

}

semi": [0, "never"] 代表,js无 分号结尾,0代表有分号结尾也不报错。

其配置说明参见:

https://eslint.org/docs/rules/

https://blog.csdn.net/helpzp2008/article/details/51507428

 

使用 commitlint 检查 git commit规范

使用的@commitlint这个插件,其配置文件commitlint.config.js 如下:

module.exports = {

  extends: ['@commitlint/config-angular']

};

其允许的注释前缀如下:

['build',

  'ci',

  'docs',

  'feat',

  'fix',

  'perf',

  'refactor',

  'revert',

  'style',

  'test'

]

例如 git commit -a -m 'build: refactor' 是合格的注释。

 

具体参见:

https://www.npmjs.com/package/@commitlint/config-angular

https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/commitlint.config.js

 

使用 IDE 的 EditorConfig 插件规范 文件文本格式

vscode 请安装插件:CTRL+SHIFT+X 搜索 EditorConfig 并安装,

然后在项目中新建 .editorconfig 文件,内容如下:

root = true

 

[*]

charset = utf-8

indent_style = space

indent_size = 2

end_of_line = lf

insert_final_newline = true

trim_trailing_whitespace = true

 

[*.md]

insert_final_newline = false

trim_trailing_whitespace = false

这个工具的一个重要作用是,将新建文件和保存的文件,自动更正 为 lf 换行符。(不然的话,windows默认的换行符是 crlf)

 

具体说明参见:http://editorconfig.org

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/818132
推荐阅读
相关标签
  

闽ICP备14008679号