创建项目
新建文件夹airspeed
执行 npm init
会生成一个简单的json文件:
{
"name": "airspeed",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
新建src文件夹,再健src/index.js文件。
新建两个object的工具函数:
isEmptyObject
.js
/**
*
* @desc 判断`obj`是否为空
* @param {Object} obj
* @return {Boolean}
*/
function isEmptyObject(obj) {
if (!obj || typeof obj !== 'object' || Array.isArray(obj))
return false
return !Object.keys(obj).length
}
module.exports = isEmptyObject
isPlainObject.js
/**
* @desc 判断obj是否为纯粹的对象{}
* @param {Object} obj
* @returns {Boolean}
*/
function isPlainObject(obj) {
if(typeof obj !== 'object' || !obj) return false;
var proto = obj;
while(Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto);
}
return Object.getPrototypeOf(obj) === proto;
}
module.exports = isPlainObject;
完成src/index.js文件
这个文件负责把所有的工具函数暴露出去。
const isEmptyObject = require('./object/isEmptyObject.js');
const isPlainObject = require('./object/isPlainObject');
let moduleExports = {
isEmptyObject,
isPlainObject
};
module.exports = moduleExports;
上面的这种写法可以简单易懂,但是如果src下面的工具函数越来越多,在index.js文件中的引入将会很长,难以维护,可以使用下面这种方式处理,不需要每次新建一个工具函数就手动引入。
/**
* @desc webpack打包入口文件
* @example 自动引入子目录下所有js文件
*/
let moduleExports = {};
const r = require.context('./', true, /^\.\/.+\/.+\.js$/);
r.keys().forEach(key => {
let attr = key.substring(key.lastIndexOf('/') + 1, key.lastIndexOf('.'));
moduleExports[attr] = r(key);
});
module.exports = moduleExports;
注意:文件名跟方法名同名
配置webpack
这里使用webpack进行打包。
新建scripts文件夹,创建webpack.config.js文件。
zhi cconst path = require('path');
const pkg = require('../package.json');
const rootPath = path.resolve(__dirname, '../');
const config = {
mode: 'production',
entry: path.resolve(rootPath,'src', 'index.js'),
output: {
filename: `${pkg.name}.min.js`,
path: path.resolve(rootPath, 'min'),
library: `${pkg.name}`, // 模块名称
libraryTarget: "umd" // 支持CommonJS、AMD, 全局对象
},
module: {
rules: [{
test: /\.js$/,
loader: "babel-loader" // 处理js文件 Babel 是一个 JavaScript 编译器。(把浏览器不认识的语法,编译成浏览器认识的语法。)
}]
}
}
module.exports = config;
新建.babelrc文件:
{
"presets":[
["@babel/preset-env", {
// 一般在webpack 项目中,我们会将此参数设置为false,既将module交由webpack处理,而不是babel。
"modules": false
}]
],
"plugins":[]
}
安装依赖
webpack 4.x | babel-loader 8.x | babel 7.x
npm install -D babel-loader @babel/core @babel/preset-env webpack@4 webpack-cli
安装好以后,就可以执行打包了:
"scripts": {
"build": "webpack --config script/webpack.config.js",
},
npm run build打包后,生产min/airspeed.min.js文件。打包后的结构大致如下:
airspeed(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["airspeed"] = factory();
else
root["airspeed"] = factory();
})(window, function() {
return _entry_return_;
});
由上面代码可以看出,模块 支持CommonJS、AMD
和全局对象。
意思就是,支持下面的几种方式引入:
CommonJS
cosnt airspeed= require("airspeed");
ES6
import airspeed from "airspeed";
AMD
require(['airspeed',], function (airspeed){
// some code here
});
全局对象
<script src="airspeed.min.js"></script>
<script>
var OS = airspeed.getOS();
</script>
配置按需引入模式
上文配置只是完成了打包,一般情况下到这里就可以直接发布到npm了,如果可以正常发布成功,就可以直接引入使用了。
但是如果我项目中只用到了一个函数,上面的方式引入会把整个工具包引入。怎么实现只引入我需要的函数呢?像这样引入:
const isEmptyObject = require("airspeed/isEmptyObject");
可以把src下面所有的js文件都复制到根目录下,发布的时候把根目录下的文件也发布上去,这样引入的时候就可以使用上面的方式了,使用哪个文件引入哪个就可以了。
script文件夹下增加两个文件:
build-copy.js
用来复制函数文件到根目录下:
const path = require('path')
const fs = require('fs')
const ora = require('ora')
const rm = require('rimraf')
const copy = require('copy')
const chalk = require('chalk')
const rootPath = path.resolve(__dirname, '../')
// 替换模块文件
let copying = ora('copying...')
copying.start()
rm('*.js', err => {
if (err) throw (err)
let folderList = fs.readdirSync(path.resolve(rootPath, 'src'))
folderList.forEach((item, index) => {
copy(`src/${item}/*.js`, rootPath, function (err, files) {
if (err) throw err;
if (index === folderList.length - 1) {
console.log(chalk.cyan(' Copy complete.\n'))
copying.stop()
}
})
})
})
build-pack.js
这个文件就是用来打包的:
const path = require('path')
const ora = require('ora')
const rm = require('rimraf')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('./webpack.conf')
const pkg = require('../package.json')
const rootPath = path.resolve(__dirname, '../')
// 构建全量压缩包
let building = ora('building...')
building.start()
rm(path.resolve(rootPath, 'min', `${pkg.name}.min.js`), err => {
if (err) throw (err)
webpack(config, function (err, stats) {
if (err) throw (err)
building.stop()
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
console.log(chalk.cyan(' Build complete.\n'))
})
})
修改build.js文件:
require('./build-copy');
require('./build-pack');
修改package.json文件:
"scripts": {
"build": "node script/build.js",
"build-copy": "node script/build-copy.js",
"build-pack": "node script/build-pack",
"test": "echo \"Error: no test specified\" && exit 1"
},
安装依赖
cnpm i rimraf chalk ora copy -D
执行npm run build
这个过程如果有报错,降低模块的版本重试。打包后的文件如下:(my-outils后更名为airspeed)
发布
1 完善配置文件
npm忽略文件.npmignore:
src/
scripts/
node_modules/
.babelrc
.gitignore
git忽略文件:
node_modules/
发不到自己的git账号以后,修改package.json文件:
{
"name": "airspeed",
"version": "1.0.0",
"description": "JavaScript utils",
"main": "min/airspeed.min.js",
"scripts": {
"build": "node script/build.js",
"build-copy": "node script/build-copy.js",
"build-pack": "node script/build-pack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/artadmire/airspeed.git"
},
"keywords": [
"outil",
"tool",
"common-util"
],
"author": "MaiLe",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"babel-loader": "^8.2.3",
"chalk": "^4.1.2",
"copy": "^0.3.2",
"ora": "^5.4.1",
"rimraf": "^3.0.2",
"webpack": "^4.46.0",
"webpack-cli": "^4.9.2"
}
}
2 发布
2.1 npm账号
登陆npm账号,如果没有就注册一个。
2.2 npm adduser
使用 npm adduser
命令来添加npm的账户名、密码和邮箱。
如果你使用的是淘宝镜像,切换回原镜像:npm config set registry https://registry.npmjs.org
2.3 npm login
这一步跟上面是一样的。
2.4 npm publish
如果没有报错说明发布成功了。
如果看下下面的报错,则需要验证邮箱。
在浏览器中登陆npm看到下面的提示:
根据提示,点击here一步一步完成邮箱验证就可以了。已经测似可以使用,如果验证过程会有些问题,就多尝试几次,结果可能有延迟。
验证好以后尝试重新登录。
工具包发布成功以后,引入试试看:
npm i airspeed -D
const isEmptyObject = require('airspeed/isEmptyObject')
isEmptyObject({})
node index.js文件 控制台输出true