资讯专栏INFORMATION COLUMN

从 1 到完美,写一个 js 库、node 库、前端组件库

rollback / 1832人阅读

摘要:从到完美,写一个库库前端组件库之前讲了很多关于项目工程化前端架构前端构建等方面的技术,这次说说怎么写一个完美的第三方库。使用导出模块,就可以在使用这个库的项目中构建时使用功能。

从 1 到完美,写一个 js 库、node 库、前端组件库

之前讲了很多关于项目工程化、前端架构、前端构建等方面的技术,这次说说怎么写一个完美的第三方库。

1. 选择合适的规范来写代码

js 模块化的发展大致有这样一个过程 iife => commonjs/amd => es6,而在这几个规范中:

iife: js 原生支持,但一般不会直接使用这种规范写代码

amd: requirejs 定义的加载规范,但随着构建工具的出现,便一般不会用这种规范写代码

commonjs: node 的模块加载规范,一般会用这种规范写 node 程序

es6: ECMAScript2015 定义的模块加载规范,但到目前为止,几乎所有的 js 运行环境都不支持,包括浏览器、node(包括 electronnw.js)、React Native

针对原生不支持任何规范的运行环境程序(如浏览器、React Native),建议使用 es6 规范来写代码,然后由工具转换成原生 js 能够运行的。

而针对 node 程序,可以直接用 commonjs 规范来写,也可由 es6 规范来写,然后用工具转化成 commonjs 规范。

所以,总的来说,都可以使用 es6 规范来写代码,然后用工具转换成其他规范,而且 es6 的代码可以使用 tree-shaking 功能。

参考:

IIFE(Immediately-invoked function expression)

requirejs、electron、nw.js、react-native

Tree shaking

2. 选择合适的构建工具

对于前端项目来说,因为有静态资源(如图片、字体等)加载与按需加载的需求,所以使用 webpack 是不二选择,但对于第三方库来说,其实还有更好的选择:rollup

可以查看 webpack 之外的另一种选择:rollup 了解 webpackrollup 之间各自的差异与优势。

webpack 在打包成第三方库的时候只能导出 amd/commonjs/umd,而 rollup 能够导出 amd/commonjs/umd/es6。使用 rollup 导出 es6 模块,就可以在使用这个库的项目中构建时使用 tree-shaking 功能。

对于有样式文件(csslessscss)、静态资源文件(图片、字体)的前端组件来说,可以使用 rollup-plugin-postcss 插件配合 rollup 处理样式文件与静态资源文件。

参考:

webpack、rollup、rollup-plugin-postcss

webpack 之外的另一种选择:rollup

UMD (Universal Module Definition)

tree-shaking

webpack 如何优雅的使用tree-shaking(摇树优化)

3. 定好目录结构

一般库项目的目录:

|-- /                   # 项目根目录
    |-- src/            # 源代码目录
    |-- lib/(dist/)     # 发布文件目录
    
    |-- test/           # 测试文件目录
    |-- ...             # 更多其他目录

如果是多包项目(一个项目里有多个 npm packages,比如 babel):

|-- /                           # 项目根目录
    |-- packages/               # packages 目录   
        |-- pkg1/               # package1 目录
            |-- src/            # 源代码目录
            |-- lib/(dist/)     # 发布文件目录
        |-- pkg2/               # package2 目录
            |-- src/            # 源代码目录
            |-- lib/(dist/)     # 发布文件目录
            
        |-- ...
                   

后面会详细讲解多包项目。

4. 搭建一个好的脚手架

不管是应用项目还是第三方库项目,都需要搭建一个好的脚手架,来帮助我们更好的编写代码、构建项目等。

可以查看 搭建自己的前端脚手架 了解一些基本的脚手架文件与工具。

比如:

.editorconfig: 用这个文件来统一不同编辑器的一些配置,比如 tab 转 2 个空格、自动插入空尾行、去掉行尾的空格等,http://editorconfig.org

eslint、stylelint、prettier: 规范化代码风格、优化代码格式等

husky、lint-staged: 在 git 提交之前对代码进行审查,否则不予提交

.travis.yml: 一个很棒的持续集成服务,https://www.travis-ci.org/

详细的文件、工具与配置,参考 搭建自己的前端脚手架。

另外,针对开源的第三方库,还可以有:

LICENSE: 协议文件

CONTRIBUTING.md: 项目代码参与者

codecov.yml: 测试覆盖率配置文件

.github: github 上的一些自定义配置,比如 issue 模板、pr 模板等

/docs: 文档目录

/examples: 使用示例目录

/scripts: 脚本目录

加上 rollup 的配置文件 rollup.config.js:

rollup.config.js

如果是 node 程序,把 es6 规范转化成 commonjs 规范:

export default {
  input: "src/index.js",
  output: {
    file: "lib/index.js",
    format: "cjs",
  },
};

如果是前端库,还需要转 es6+es5、导出不同规范的文件(es6/commonjs/amd/umd):

import babel from "rollup-plugin-babel";
import postcss from "rollup-plugin-postcss";

export default [
  {
    file: "lib/cjs.js",
    format: "cjs",
  },
  {
    file: "lib/m.js",
    format: "esm",
  },
  {
    file: "lib/umd.js",
    format: "umd",
    name: "Name",
  },
  {
    file: "lib/amd.js",
    format: "amd",
  },
].map(output => ({
  input: "src/index.js",
  output,
  plugins: [
    babel({
      presets: ["@babel/preset-env"],
    }),
    postcss({ extract: !0 }), // 构建样式文件时需要这个插件
  ],
}));
.gitignore

一般来说,我们并不希望把发布文件放到 git 的版本控制之中,而只是发布到仓库而已,所以:

# .gitignore

.DS_Store
node_modules
bower_components
/coverage
*.log
.idea
.vscode
.eslintcache
package-lock.json

/lib                        # 把 lib 排除在外
/packages/*/lib             # 多包项目
package.json
{
  ...
  # node 项目
  "main": "lib/index.js",
  
  # 前端项目
  "main": "lib/cjs.js",              # commonjs 规范文件
  "module": "lib/m.js",              # es6 规范文件
  "umd:main": "lib/umd.js",          # umd 规范文件
  "amd:main": "lib/amd.js",          # amd 规范文件
  
  "files": [                         # 发布时只发布 lib 目录下文件
    "lib"
  ],
  "scripts": {
    ...
    "build": "rollup -c",            # 构建发布文件
    "prepublishOnly": "npm run build",    # npm publish 之前先 npm run build
    "pretest": "npm run build",      # npm run test 之前先 npm run build
  },
  ...
}

在实际项目中,构建工具(如 webpack)会首先找这个包中的 module 字段对应的 es6 规范文件,并使用 tree-shaking;如果不存在,然后找 main 字段对应的文件。

有些构建工具可能也会用 amd 规范文件与 umd 规范文件。

参考:

搭建自己的前端脚手架

5. 构建多包项目

如果一个项目很大,需要分割成多个 npm 包进行管理,但这些包仍然在一个项目里,并且这些包可能有相互依赖关系,这个时候就比较难以管理和开发了。

为了方便的管理多包项目,lerna 便应运而生,babel、create-react-app、jest、lila 等都是用 lerna 来管理多个包的。

英文不好的童鞋,可以参考 使用lerna管理大型前端项目,了解 lerna 的一些基本用法。

lerna 一般目录文件结构
my-lerna-repo/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.json
安装 lerna,初始化项目
# 安装
npm i -g lerna
# 初始化
git init lerna-repo && cd lerna-repo
lerna init
# 初始化后的目录及文件
lerna-repo/
  packages/
  package.json
  lerna.json
配置文件 lerna.json
{
  "version": "0.5.2",             # 当前版本号
  "packages": [
    "packages/*"
  ],
  "command": {
    "publish": {                  # 发布配置
      "ignoreChanges": [          # 哪些文件变动不会引发发布新版本
        "*.md",
        "*.json",
        "*.txt",
        "test/**",
        "example/**",
        "package.json"
      ]
    },
    "bootstrap": {
      "npmClient": "cnpm"         # lerna bootstrap 时使用哪个 npm 客户端
    }
  },
  "npmClientArgs": [              # npm 客户端 运行时的参数
    "--no-package-lock"
  ]
}
常用命令 lerna publish: 发布所有有更新的包

在默认的固定模式(Fixed mode)下,这个命令会检查 packages 目录下哪些包的文件有更新(lerna.jsoncommand.publish.ignoreChanges 除外),然后把 lerna.json 中的 version 与有更新的包中 package.jsonversion 字段更新到一个新的版本号上,最后把这些有更新的包都发布到远程仓库上。

lerna bootstrap: 启动建立包相互之间的 node_modules 链接

这个命令会根据各个包下 package.json 里面的 dependenciesdevDependencies 配置,使用 symlink 在各个包的 node_modules 下面建立引用关系。这样就解决了相互之间有依赖而无法联调的问题。

lerna changed: 查看哪些包有更新,可以发布一个新的版本 lerna diff [package?]: 查看包都更新了些什么 lerna run [script]: 使用 npm 运行每个包下面的 [script]

参考:

lerna

使用lerna管理大型前端项目

6. 示例

单个包的 node 项目可以参考我的项目:sclean

单个包的前端项目可以参考我的项目:see-fetch

多个包的项目可以参考我的项目:lila

后续

更多博客,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/114233.html

相关文章

  • 1 完美一个 js node 前端组件

    摘要:从到完美,写一个库库前端组件库之前讲了很多关于项目工程化前端架构前端构建等方面的技术,这次说说怎么写一个完美的第三方库。使用导出模块,就可以在使用这个库的项目中构建时使用功能。 从 1 到完美,写一个 js 库、node 库、前端组件库 之前讲了很多关于项目工程化、前端架构、前端构建等方面的技术,这次说说怎么写一个完美的第三方库。 1. 选择合适的规范来写代码 js 模块化的发展大致有...

    xiaolinbang 评论0 收藏0
  • 1 完美,用 js 和 react-native 一个 APP

    摘要:从到完美,用和写一个在年开源了后,紧接着在年就又开源了,就此打开了用和前端技术写原生之路。对应来看,程序只有两个部分,和,而部分则分为组件和。所以,在端的纯库无在中同样适用,如等。应用实例便是使用开发的一个日记。 从 1 到完美,用 js 和 react-native 写一个 APP facebook 在 2013 年开源了 react 后,紧接着在 2015 年就又开源了 react...

    CollinPeng 评论0 收藏0
  • 0 1 100, 搭建、编、构建一个前端项目

    摘要:从到再到搭建编写构建一个前端项目选择现成的项目模板还是自己搭建项目骨架搭建一个前端项目的方式有两种选择现成的项目模板自己搭建项目骨架。使用版本控制系统管理源代码项目搭建好后,需要一个版本控制系统来管理源代码。 从 0 到 1 再到 100, 搭建、编写、构建一个前端项目 1. 选择现成的项目模板还是自己搭建项目骨架 搭建一个前端项目的方式有两种:选择现成的项目模板、自己搭建项目骨架。 ...

    call_me_R 评论0 收藏0
  • 0 1 100, 搭建、编、构建一个前端项目

    摘要:从到再到搭建编写构建一个前端项目选择现成的项目模板还是自己搭建项目骨架搭建一个前端项目的方式有两种选择现成的项目模板自己搭建项目骨架。使用版本控制系统管理源代码项目搭建好后,需要一个版本控制系统来管理源代码。 从 0 到 1 再到 100, 搭建、编写、构建一个前端项目 1. 选择现成的项目模板还是自己搭建项目骨架 搭建一个前端项目的方式有两种:选择现成的项目模板、自己搭建项目骨架。 ...

    wzyplus 评论0 收藏0
  • 0 1 100, 搭建、编、构建一个前端项目

    摘要:从到再到搭建编写构建一个前端项目选择现成的项目模板还是自己搭建项目骨架搭建一个前端项目的方式有两种选择现成的项目模板自己搭建项目骨架。使用版本控制系统管理源代码项目搭建好后,需要一个版本控制系统来管理源代码。 从 0 到 1 再到 100, 搭建、编写、构建一个前端项目 1. 选择现成的项目模板还是自己搭建项目骨架 搭建一个前端项目的方式有两种:选择现成的项目模板、自己搭建项目骨架。 ...

    aristark 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<