从 1 到圆满,写一个 js 库、node 库、前端组件库

从 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 功用。

参考:

2. 挑选适宜的构建东西

关于前端项目来讲,由于有静态资本(如图片、字体等)加载与按需加载的需求,所以运用 webpack 是不贰挑选,但关于第三方库来讲,实在另有更好的挑选:rollup

能够检察 webpack 以外的另一种挑选:rollup 相识 webpackrollup 之间各自的差别与上风。

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

关于有款式文件(csslessscss)、静态资本文件(图片、字体)的前端组件来讲,能够运用 rollup-plugin-postcss 插件合营 rollup 处置惩罚款式文件与静态资本文件。

参考:

3. 定好目次构造

平常库项目的目次:

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

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

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

后面会细致解说多包项目。

4. 搭建一个好的脚手架

不管是运用项目照样第三方库项目,都须要搭建一个好的脚手架,来协助我们更好的编写代码、构建项目等。

能够检察 搭建本身的前端脚手架 相识一些基础的脚手架文件与东西。

比方:

细致的文件、东西与设置,参考 搭建本身的前端脚手架

别的,针对开源的第三方库,还能够有:

  • 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 便应运而生,babelcreate-react-appjestlila 等都是用 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]

参考:

6. 示例

单个包的 node 项目能够参考我的项目:sclean

单个包的前端项目能够参考我的项目:see-fetch

多个包的项目能够参考我的项目:lila

后续

更多博客,检察 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版权声明:自在转载-非商用-非衍生-坚持签名(创意同享3.0许可证

    原文作者:senntyou
    原文地址: https://segmentfault.com/a/1190000017064659
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞