概述
npm包有什么用
有的同学在开发的过程中,经常会造一些“轮子”,也就是一些复用性比较强的库(工具函数库或者组件库),那么将这些“轮子”发布成自己的一个npm包,绝对会给你带来工作效率的提升。
为什么用TypeScript
引用 TypeScrip教程 内提及的内容:
TypeScript 增加了代码的可读性和可维护性
- 类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了
- 可以在编译阶段就发现大部分错误,这总比在运行时候出错好
- 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、代码重构等
TypeScript 非常包容
- TypeScript 是 JavaScript 的超集,
.js
文件可以直接重命名为.ts
即可- 即使不显式的定义类型,也能够自动做出类型推论
- TypeScript 的类型系统是图灵完备的,可以定义从简单到复杂的几乎一切类型
- 即使 TypeScript 编译报错,也可以生成 JavaScript 文件
- 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取
其中,对于npm上的包来说。在使用包内的工具时候,上述的接口提示就十分强大。
可以用JavaScript吗
有些不会TypeScrip的同学可能说,这篇不适合我看。错!
本篇内容也可以采用
JavaScript
的方式去写,去发布使用。完全是适配的。因为我们使用TypeScript
,目的还是约束开发规范之类的问题,最终还是得通过打包成.js
文件。如若用JavaScript
的方式去写,完全可以的,文末也会6.2处也会提及具体相关。上述:TypeScript 是 JavaScript 的超集,.js 文件可以直接重命名为 .ts 即可也能体现两者的关系。
具体操作内容
本文采用vue-cli3
工具创建TypeScript
项目,目的是为了让读者更清晰看到自己写的工具方法(写组件同理)能及时的验证,让我们知悉在源码编写这一层面上是没有问题。通过写几个简单工具方法,然后打包,发布到npm上,最后在项目中安装自己发布的包。目的是:成功调用自己写的包内的方法。
本文项目地址
github地址:https://github.com/chenjing0823/util-tools
npm包地址:https://www.npmjs.com/package/common-util-tools
操作步骤
1、创建项目
vue create util-tools
然后选择Babel
、Typescript
、Unit Testing
、Jest
其余默认
运行项目后,正常打开vue默认页后。项目创建完成,可以继续操作,关闭服务。
2、目录调整
之所以需要目录调整,是因为我们利用采用vue-cli3
工具创建了TypeScript
+vue
的一个项目,其中在本项目内,我们只是要写一个utils
工具包,而vue的页面实例仅仅是用来校验我们的工具是否可用可行。
所以目录调整的目的,是将包代码合页面实例代码区分开。
-
- 在根同目录下,创建一个example文件夹,将src移动至改文件夹内(页面实例,用于验证方法,与工具包无关)
-
- 在根目录下创建src,用于放我们写的工具包函数方法
-
- tsconfig.json内,需要修改以下内容(新增3个example/src/)
{
// ...其他配置
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"example/src/**/*.ts",
"example/src/**/*.tsx",
"example/src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
]
// ...其他配置
}
3、源码编写
src/index.ts:
如果对于下面4个文件存在疑惑,且比较注重发布这个过程,也可以直接在index.ts内直接export自己写的方法,不写其他几个文件方法。
import * as env from "./util-tool/env"; // 方法集合1
import * as is from "./util-tool/is"; // 方法集合2
import { Types } from "./types";
import { mixin } from "./tools/index";
function initUtils(): Types {
const instance = Object.create(null);
const arr = [env, is];
mixin(instance, arr);
return instance as Types;
}
const _utils = initUtils();
export default _utils;
src/util-tool/env
utils工具方法1
/**
*
* @ignore
* @return {boolean} 判断当前浏览器是移动端(false)还是pc端(true)
*
*/
export function getEnv(): boolean {
const userAgent = navigator.userAgent;
const device: string[] = [
"Android",
"iPhone",
"SymbianOS",
"Windows Phone",
"iPad",
"iPod"
];
let flag = true;
for (let i = 0; i < device.length; i++) {
if (userAgent.indexOf(device[i]) !== -1) {
flag = false;
break;
}
}
return flag;
}
src/util-tool/is
utils工具方法2
export function isArray(value: any): value is Array {
return typeof value !== "undefined" && value instanceof Array;
}
export function isObject(value: any): value is Record {
return value !== null && typeof value === "object";
}
src/types
interface Env {
/**
*
* 判断当前浏览器是移动端还是pc端
* @return {boolean} pc: true; mobile: false
* @author superjing
* ``` typescript
* const env = utils.getEnv()
* ```
*/
getEnv(): boolean;
}
interface Is {
/**
*
* 判断是否是数组
* @param value 传入需要判断的变量
* @return {boolean} true | false
* @author superjing
* ``` typescript
* utils.isArray([1, 2]) // true
* ```
*
*/
isArray(value: any): boolean;
}
export interface Types extends Env, Is {}
tools/index
export function mixin(to: T, from: Array): T {
from.forEach(obj => {
Object.getOwnPropertyNames(obj).forEach(key => {
to[key] = obj[key];
});
});
return to;
}
4、项目配置
简单的配置,易理解
/build/config.doc.js
该配置调试example文件夹中的页面实例,在这个单页面中可以直接使用以及测试编写的工具方法
const path = require("path");
const resolve = dir => path.join(__dirname, "../", dir);
console.log("run doc");
module.exports = {
publicPath: "./",
devServer: { port: "8000" },
outputDir: resolve("docs"),
pages: {
index: {
entry: resolve("example/src/main.ts"),
template: "public/index.html",
filename: "index.html",
title: "Index Page",
chunks: ["chunk-vendors", "chunk-common", "index"]
}
},
chainWebpack: config => {
config.plugins.delete("prefetch-index");
}
};
/build/config.lib.js
配置打包utils工具包,打包不包括example文件夹下的示例页面,仅仅是index.ts中实现的函数,打包目标为umd格式,兼容浏览器,node以及es6模块规范;
const path = require("path");
const resolve = dir => path.join(__dirname, "../", dir);
console.log("run lib");
module.exports = {
outputDir: resolve("dist"),
configureWebpack: {
entry: {
utils: resolve("src/index.ts")
},
output: {
filename: `[name].js`,
libraryTarget: "umd",
libraryExport: "default",
library: "utils",
globalObject: "this"
}
},
css: {
extract: {
filename: `[name].css`
}
},
chainWebpack: config => {
config.optimization.delete("splitChunks");
config.plugins.delete("copy");
config.plugins.delete("preload");
config.plugins.delete("prefetch");
config.plugins.delete("html");
config.plugins.delete("hmr");
config.entryPoints.delete("app");
}
};
/build/index.js
module.exports =
process.env.NODE_ENV === "production"
? require("./config.lib")
: require("./config.doc");
/vue.config.js
module.exports = require("./build/index");
到这为止,配置完成。下面进行工具调试
5、本地调试
/example/src/App.vue
下图可以看到,用typescript开发的提示功能
启动服务(确认4、项目配置无误后,方可正常启动)
npm run serve
可以看到写的工具可以正常使用:
6、打包发布
6.1 打包
在4、项目配置的config.lib.js
内,已经写了打包相关内容,运行打包命令
npm run build
在目录处生成dist
文件夹,内有生成的utils.js
同样,在根目录建一个demo.html,直接引入打包生成的js
Title
同样可以正常使用,于是工具包便算开发完成,可以自己发布了(若公司内要规范npm的包,还需要进行单元测试,我们构建项目的时候已经选择了
Unit Testing、Jest
)
6.2 发布
通过该文件,其实也可以看到,若是用JavaScript
写该插件,也是极其方便的,只要把最后打包生成的js设为mian的入口即可。对typescript
有不熟悉的,也可以用JavaScript
进行开发
修改package.json
{
"name": "common-util-tools", // 包名,不能跟已有的包名有重复
"version": "0.1.0", // 每次发布需要修改版本号
"private": false, // 需要设置false
"author": "chenjing0823",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
},
"repository": {
"type": "git",
"url": "https://github.com/chenjing0823/util-tools"
},
"license": "MIT",
"main": "dist/utils.js", // 入口需要正确
"keywords": [
"utils",
"tools"
],
"files": [
"dist"
],
// ...其余代码
}
然后发布(需要注册npm账户,并先登陆自己的npm账号发布)
npm publish
发布成功后,大概在短暂的延迟过后,就可以在https://www.npmjs.com/搜到自己发布的插件了。
对于发布有问题的,可以参考发布npm包时遇到的一些坑
7、安装调用
到上述为止,包的创建、编写、发布已经完成了,现在来试用一下试试:
7.1 新建一个空文件夹
在该文件夹下init生成一个空项目
npm init -y
7.2 安装我们的包
npm install common-util-tools -D
可以在package.json内看到:
7.3 新建一个index.js
const utils = require('common-util-tools')
console.log(123);
console.log("utils.isArray([]) is array is:", utils.isArray([]));
console.log("utils.isArray('') is array is:", utils.isArray(""));
7.4 使用测试
node index.js
到此,我们从创建项目 - > 编写代码 - > 项目配置 - > 打包发布 - > 包的使用,已经大功告成,后续读者朋友就可以写出自己的一套东西去发布使用。例如一些公共组件的编写,公共方法的编写。