如何搭建npm包

hujiao發表於2019-01-23

本文將從以下幾個方面分享如何搭建一個npm包,在搭建過程中需要注意的事項

  • 初始化
  • 入口
  • 依賴
  • 檔案
  • 版本號管理
  • 自動化釋出

初始化

在專案根目錄下執行:npm init 建立 package.json 檔案,這也是npm包的核心配置檔案

入口

package.json 中可以通過下面兩個欄位來指定入口檔案:

  • main 指向 commonjs 模組的入口,使用 require 語法引入
  • module 指向 ES2015 模組的入口,使用 import 語法引入,支援webpack等構建工具的 tree shaking 優化

這裡,可以展開介紹一下 umd、commonjs、es module 模組型別的區別

  • umd 是相容 commonjs、amd 的通用模組規範,支援全變數規範,可以直接通過<script>標籤引入,寫法如下:
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global['xxx'] = factory());
}(this, (function () { 'use strict';
    ...
})));
複製程式碼
  • commonjs 使用module.exports定義模組對外輸出的介面,使用require載入模組
  • es module 是ES6模組,使用exportimport語法

而一般npm包都需要支援以上三種模組規範,以下列出通用的rollup配置:

import path from 'path';
import babel from 'rollup-plugin-babel';
import cleanup from 'rollup-plugin-cleanup';
import replace from 'rollup-plugin-replace';
import { uglify } from 'rollup-plugin-uglify';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import pkg from './package.json';

const { version, name, author } = pkg;

const banner = `/*!
* ${name} v${version}
* (c) ${new Date().getFullYear()} ${author}
*/`;

const resolve = p => {
    return path.resolve(__dirname, p);
}

const pluginsCommon = [
    commonjs({
        // polyfill async/await
        'node_modules/@babel/runtime/helpers/asyncToGenerator.js': ['default']
    }),
    nodeResolve({
        module: false,
    }),
    babel({
        runtimeHelpers: true,
    }),
]

export default [
    {
        input: resolve('src/index.js'),
        plugins: pluginsCommon.concat([
            cleanup(),
        ]),
        output: {
            file: resolve(`dist/npmpackage-name-${version}.js`),
            format: 'umd',
            name: 'npmpackage-name',
            banner,
        }
    },
    {
        input: resolve('src/index.js'),
        plugins: pluginsCommon.concat([
            uglify(),
        ]),
        output: {
            file: resolve(`dist/npmpackage-name-${version}.min.js`),
            format: 'umd',
            name: 'npmpackage-name',
            banner,
        }
    },
    {
        input: resolve('src/index.js'),
        plugins: pluginsCommon.concat([
            cleanup(),
        ]),
        output: [
            {
                file: resolve(`dist/npmpackage-name.es.js`),
                format: 'es',
                banner,
            },
            {
                file: resolve(`dist/npmpackage-name.js`),
                format: 'cjs',
                banner,
            }
        ]
    },
];
複製程式碼

再附上對應的babel配置:

{
    "presets": [
        ["@babel/preset-env", {
            "targets": {
                "browsers": ["Android >= 4", "iOS >= 8"]
            },
            "modules": false,
            "loose": true
        }]
    ],
    "plugins": [
        "@babel/plugin-external-helpers",
        [
            "@babel/plugin-transform-runtime",
            {
                "regenerator": true
            }
        ]
    ]
}
複製程式碼

以上,配置則能構建出滿足以上三種模組規範的檔案

相應的package.json檔案中,也需要通過不同的欄位,來指定對應模組規範的入口檔案,如下:

{
    ...
    "main": "dist/npmpackage-name.js",
    "module": "dist/npmpackage-name.es.js",
    ...
}
複製程式碼

dist/npmpackage-name-${version}.js的檔案,則可以直接通過<script>標籤引入

注意:不要將入口檔案指定為未過babel的檔案,這往往會導致使用了此包的專案出現相容問題

依賴

package.json中跟npm包依賴相關的欄位主要有:

  • dependencies:專案執行時所依賴的模組
  • devDependencies:專案開發時所依賴的模組
  • peerDependencies:這是“同伴依賴”,一種特殊的依賴,在釋出包的時候需要。有這種依賴意味著安裝包的使用者也需要和包同樣的依賴。(在安裝包時會提示)

我們在開發npm包過程中,需要注意安裝依賴的型別。

對於那些對版本有強要求的依賴,為了避免因依賴版本不一致導致問題,需要將此類依賴安裝在 peerDependencies 中

檔案

一個npm包一般包括原始檔、構建產出的檔案、demo檔案、測試檔案等檔案,而為了減小npm包大小,加快下載速度,釋出時應該將無用的檔案剔除掉,有兩種方式:

  • 使用 package.json 中的 files 指定需要釋出的檔案
  • .npmignore 檔案中指定需要提出的檔案

版本號管理

每釋出一個版本,版本號需要相應的升級(不要手動在package.json中維護)

應該通過npm version來對版本號進行管理,版本號有以下幾種型別:

  • major: 主版本號
  • minor: 次版本號
  • patch: 補丁號
  • premajor: 預備主版本
  • preminor: 預備次版本
  • prepatch: 預備補丁號
  • prerelease: 預釋出版本

版本號管理策略如下:

  • 版本號格式:主版本號.次版本號.修訂號
  • 主版本號:有不相容的 API 修改
  • 次版本號:有向後相容的功能性新增
  • 修訂號:有向後相容的問題修正

而升級對應的版本號的命令則如下:

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
複製程式碼

釋出自動化

package.json配置如下:

{
    "scripts": {
        "build": "rm -rf dist && rollup --config",
        "release_major": "npm version major",
        "release_minor": "npm version minor",
        "release_patch": "npm version patch",
        "postversion": "npm publish",
        "prepublishOnly": "npm run build"
    },
}
複製程式碼

直接通過執行對應的release_命令來進行釋出即可

以上就是一個npm包通常會用到基本事項,後續會不斷更新一些進階的用法~

寫在最後

希望能對有需要的小夥伴有幫助~~~

喜歡我的文章小夥伴可以去 我的個人部落格 點star ⭐️

相關文章