真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何創(chuàng)建并發(fā)布npm包

這篇文章主要介紹“如何創(chuàng)建并發(fā)布npm包”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“如何創(chuàng)建并發(fā)布npm包”文章能幫助大家解決問題。

額敏ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!

工具庫準(zhǔn)備

創(chuàng)建一個新項目,包含package.json

{
    "name": "drrq",
    "type": "module",
    "version": "1.0.0"
}

功能實現(xiàn) /src/index.js

npm i qs axios

主要思路是用請求的url和參數(shù)作為key記錄請求隊列,當(dāng)出現(xiàn)重復(fù)請求時,打斷后面的請求,將前面的請求結(jié)果返回時共享給后面的請求。

import qs from "qs";
import axios from "axios";

let pending = []; //用于存儲每個ajax請求的取消函數(shù)和ajax標(biāo)識
let task = {}; //用于存儲每個ajax請求的處理函數(shù),通過請求結(jié)果調(diào)用,以ajax標(biāo)識為key

//請求開始前推入pending
const pushPending = (item) => {
    pending.push(item);
};
//請求完成后取消該請求,從列表刪除
const removePending = (key) => {
    for (let p in pending) {
        if (pending[p].key === key) {
            //當(dāng)前請求在列表中存在時
            pending[p].cancelToken(); //執(zhí)行取消操作
            pending.splice(p, 1); //把這條記錄從列表中移除
        }
    }
};
//請求前判斷是否已存在該請求
const existInPending = (key) => {
    return pending.some((e) => e.key === key);
};

// 創(chuàng)建task
const createTask = (key, resolve) => {
    let callback = (response) => {
        resolve(response.data);
    };
    if (!task[key]) task[key] = [];
    task[key].push(callback);
};
// 處理task
const handleTask = (key, response) => {
    for (let i = 0; task[key] && i < task[key].length; i++) {
        task[key][i](response);
    }
    task[key] = undefined;
};

const getHeaders = { 'Content-Type': 'application/json' };
const postHeaders = { 'Content-Type': 'application/x-www-form-urlencoded' };
const fileHeaders = { 'Content-Type': 'multipart/form-data' };

const request = (method, url, params, headers, preventRepeat = true, uploadFile = false) => {
    let key = url + '?' + qs.stringify(params);
    return new Promise((resolve, reject) => {
        const instance = axios.create({
            baseURL: url,
            headers,
            timeout: 30 * 1000,
        });

        instance.interceptors.request.use(
            (config) => {
                if (preventRepeat) {
                    config.cancelToken = new axios.CancelToken((cancelToken) => {
                        // 判斷是否存在請求中的當(dāng)前請求 如果有取消當(dāng)前請求
                        if (existInPending(key)) {
                            cancelToken();
                        } else {
                            pushPending({ key, cancelToken });
                        }
                    });
                }
                return config;
            },
            (err) => {
                return Promise.reject(err);
            }
        );

        instance.interceptors.response.use(
            (response) => {
                if (preventRepeat) {
                    removePending(key);
                }
                return response;
            },
            (error) => {
                return Promise.reject(error);
            }
        );

        // 請求執(zhí)行前加入task
        createTask(key, resolve);

        instance(Object.assign({}, { method }, method === 'post' || method === 'put' ? { data: !uploadFile ? qs.stringify(params) : params } : { params }))
            .then((response) => {
                // 處理task
                handleTask(key, response);
            })
            .catch(() => {});
    });
};

export const get = (url, data = {}, preventRepeat = true) => {
    return request('get', url, data, getHeaders, preventRepeat, false);
};
 export const post = (url, data = {}, preventRepeat = true) => {
     return request('post', url, data, postHeaders, preventRepeat, false);
 };
 export const file = (url, data = {}, preventRepeat = true) => {
     return request('post', url, data, fileHeaders, preventRepeat, true);
 };
export default { request, get, post, file };

新增示例代碼文件夾/example

示例入口index.js

import { exampleRequestGet } from './api.js';
const example = async () => {
    let res = await exampleRequestGet();
    console.log('請求成功 ');
};
example();

api列表api.js

import { request } from './request.js';
// 示例請求Get
export const exampleRequestGet = (data) => request('get', '/xxxx', data);

// 示例請求Post
export const exampleRequestPost = (data) => request('post', '/xxxx', data);

// 示例請求Post 不去重
export const exampleRequestPost2 = (data) => request('post', '/xxxx', data, false);

// 示例請求Post 不去重
export const exampleRequestFile = (data) => request('file', '/xxxx', data, false);

全局請求封裝request.js

import drrq from '../src/index.js';
const baseURL = 'https://xxx';

// 處理請求數(shù)據(jù)  (拼接url,data添加token等) 請根據(jù)實際情況調(diào)整
const paramsHandler = (url, data) => {
    url = baseURL + url;
    data.token = 'xxxx';
    return { url, data };
};

// 處理全局接口返回的全局處理相關(guān)邏輯  請根據(jù)實際情況調(diào)整
const resHandler = (res) => {
    // TODO 未授權(quán)跳轉(zhuǎn)登錄,狀態(tài)碼異常報錯等
    return res;
};

export const request = async (method, _url, _data = {}, preventRepeat = true) => {
    let { url, data } = paramsHandler(_url, _data);
    let res = null;
    if (method == 'get' || method == 'GET' || method == 'Get') {
        res = await drrq.get(url, data, preventRepeat);
    }
    if (method == 'post' || method == 'POST' || method == 'Post') {
        res = await drrq.post(url, data, preventRepeat);
    }
    if (method == 'file' || method == 'FILE' || method == 'file') {
        res = await drrq.file(url, data, preventRepeat);
    }
    return resHandler(res);
};

測試功能

代碼寫完后,我們需要驗證功能是否正常,package.json加上

    "scripts": {
        "test": "node example"
    },

執(zhí)行npm run test

如何創(chuàng)建并發(fā)布npm包

功能正常,工具庫準(zhǔn)備完畢。

(eslint和prettier讀者可視情況選用)

打包

一般項目的打包使用webpack,而工具庫的打包則使用rollup

安裝 Rollup

通過下面的命令安裝 Rollup:

npm install --save-dev rollup

創(chuàng)建配置文件

在根目錄創(chuàng)建一個新文件 rollup.config.js

export default {
  input: "src/index.js",
  output: {
    file: "dist/drrp.js",
    format: "esm",
    name: 'drrp'
  }
};

  • input —— 要打包的文件

  • output.file —— 輸出的文件 (如果沒有這個參數(shù),則直接輸出到控制臺)

  • output.format —— Rollup 輸出的文件類型

安裝babel

如果要使用 es6 的語法進(jìn)行開發(fā),還需要使用 babel 將代碼編譯成 es5。因為rollup的模塊機制是 ES6 Modules,但并不會對 es6 其他的語法進(jìn)行編譯。

安裝模塊

rollup-plugin-babel 將 rollup 和 babel 進(jìn)行了完美結(jié)合。

npm install --save-dev rollup-plugin-babel@latest
npm install --save-dev @babel/core 
npm install --save-dev @babel/preset-env

根目錄創(chuàng)建 .babelrc

{
    "presets": [
      [
        "@babel/preset-env",
        {
          "modules": false
        }
      ]
    ]
}

兼容 commonjs

rollup 提供了插件 rollup-plugin-commonjs,以便于在 rollup 中引用 commonjs 規(guī)范的包。該插件的作用是將 commonjs 模塊轉(zhuǎn)成 es6 模塊。

rollup-plugin-commonjs 通常與 rollup-plugin-node-resolve 一同使用,后者用來解析依賴的模塊路徑。

安裝模塊

npm install --save-dev rollup-plugin-commonjs rollup-plugin-node-resolve

壓縮 bundle

添加 UglifyJS 可以通過移除注上釋、縮短變量名、重整代碼來極大程度的減少 bundle 的體積大小 —— 這樣在一定程度降低了代碼的可讀性,但是在網(wǎng)絡(luò)通信上變得更有效率。

安裝插件

用下面的命令來安裝 rollup-plugin-uglify:

npm install --save-dev rollup-plugin-uglify

完整配置

rollup.config.js 最終配置如下

import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import babel from 'rollup-plugin-babel';
import { uglify } from 'rollup-plugin-uglify';
import json from '@rollup/plugin-json'

const paths = {
    input: {
        root:  'src/index.js',
    },
    output: {
        root:  'dist/',
    },
};

const fileName = `drrq.js`;

export default {
    input: `${paths.input.root}`,
    output: {
        file: `${paths.output.root}${fileName}`,
        format: 'esm',
        name: 'drrq',
    },
    plugins: [
        json(),
        resolve(),
        commonjs(),
        babel({
            exclude: 'node_modules/**',
            runtimeHelpers: true,
        }),
        uglify(),
    ],
};

在package.json中加上

"scripts": {
    "build": "rollup -c"
},

即可執(zhí)行npm run build將/src/index.js打包為/dist/drrq.js

發(fā)包前的準(zhǔn)備

準(zhǔn)備npm賬號,通過npm login或npm adduser。這里有一個坑,終端內(nèi)連接不上npm源,需要在上網(wǎng)工具內(nèi)復(fù)制終端代理命令后到終端執(zhí)行才能正常連接。

如何創(chuàng)建并發(fā)布npm包

準(zhǔn)備一個簡單清晰的readme.md

如何創(chuàng)建并發(fā)布npm包

修改package.json

完整的package.json如下

{
    "name": "drrq",
    "private": false,
    "version": "1.3.5",
    "main": "/dist/drrq.js",
    "repository": "https://gitee.com/yuanying-11/drrq.git",
    "author": "it_yuanying",
    "license": "MIT",
    "description": "能自動取消重復(fù)請求的axios封裝",
    "type": "module",
    "keywords": [
        "取消重復(fù)請求",
    ],
    "dependencies": {
        "axios": "^1.2.0",
        "qs": "^6.11.0"
    },
    "scripts": {
        "test": "node example",
        "build": "rollup -c"
    },
    "devDependencies": {
       ...
    }
}

  • name 包名稱 一定不能與npm已有的包名重復(fù),想一個簡單易記的

  • private 是否為私有

  • version 版本

  • main 入口文件位置

  • repository git倉庫地址

  • author 作者

  • license 協(xié)議

  • description 描述

  • keywords 關(guān)鍵詞,便于檢索

每個 npm 包都需要一個版本,以便開發(fā)人員在安全地更新包版本的同時不會破壞其余的代碼。npm 使用的版本系統(tǒng)被叫做 SemVer,是 Semantic Versioning的縮寫。

不要過分擔(dān)心理解不了相較復(fù)雜的版本名稱,下面是他們對基本版本命名的總結(jié): 給定版本號 MAJOR.MINOR.PATCH,增量規(guī)則如下:

  • MAJOR 版本號的變更說明新版本產(chǎn)生了不兼容低版本的 API 等,

  • MINOR 版本號的變更說明你在以向后兼容的方式添加功能,接下來

  • PATCH 版本號的變更說明你在新版本中做了向后兼容的 bug 修復(fù)。

表示預(yù)發(fā)布和構(gòu)建元數(shù)據(jù)的附加標(biāo)簽可作為 MAJOR.MINOR.PATCH 格式的擴展。

最后,執(zhí)行npm publish就搞定啦

如何創(chuàng)建并發(fā)布npm包

如何創(chuàng)建并發(fā)布npm包

關(guān)于“如何創(chuàng)建并發(fā)布npm包”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。


網(wǎng)頁名稱:如何創(chuàng)建并發(fā)布npm包
文章源于:http://weahome.cn/article/gdejsp.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部