携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
设计思路:
对于项目开发来说,长期的积累,总结出一个常用的工具库,可能是每一个开发者心之所想的事情。
随着时间的流逝和经验的积累,会发现其实没有想象那么难
难就难在----
如何做起来?
为什么要做?
能提供什么有用的能力?
做之前需要思考一些问题:
- 通用性
- 扩展性
- 简单好用
其实这几个要求,对设计来说,难度已经非常大了。
因为我们认为的不一定是我们认为的,随着经验的积累,认知只会推翻认知。
设计实践
看过之前的文章,大概对这张图理解可能不是很难,之前的服务层的很多设计都已讲解。我对工具库的定位,放在了框架层,为上层应用提供服务。
工具库目录
构建方式
使用 rollup
打包方式,支持umd
和es
方式
打包完成后,发布npm即可
项目中npm安装依赖或者CDN方式都可以
package.json
"scripts": {
"es": "rollup --config rollup.config.es.js",
"umd": "rollup --config rollup.config.umd.js"
},
ES打包
rollup.entry.js
export default {
index: 'src/basic-utils/index.js',
EDU_DB: 'src/basic-utils/libs/db/index.js',
SocketEmitter: 'src/basic-utils/libs/event/index.js',
cache: 'src/basic-utils/libs/cache.js',
copy: 'src/basic-utils/libs/copy.js',
download: 'src/basic-utils/libs/download.js',
fullScreenHelper: 'src/basic-utils/libs/fullScreenMethods.js',
isEqual: 'src/basic-utils/libs/isEqual.js',
logger: 'src/basic-utils/libs/logger.js',
resizeHelper: 'src/basic-utils/libs/resize.js',
formatTimeStamp: 'src/basic-utils/libs/formatTimeStamp.js',
DateHelper: 'src/basic-utils/libs/formatTime.js',
queryHelper: 'src/basic-utils/libs/query.js',
pageStateHelper: 'src/basic-utils/libs/pageState.js',
treeHelper: 'src/basic-utils/libs/tree.js',
submidstr: 'src/basic-utils/libs/submidstr.js',
thousand: 'src/basic-utils/libs/thousand.js',
withPageState: 'src/basic-utils/libs/withPageState.js',
uuid: 'src/basic-utils/libs/uuid.js',
worker: 'src/basic-utils/libs/worker.js',
imageMethods: 'src/basic-utils/libs/imageMethods.js',
resizeObserver: 'src/basic-utils/libs/resizeObserver.js',
Base64: 'src/basic-utils/libs/base64.js',
};
rollup.config.es.js
/*
rollup 配置文件
*/
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import clear from 'rollup-plugin-clear';
import entry from './rollup.entry';
import pkg from './package.json';
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
const dependencies = {
...pkg.dependencies,
react: '',
};
const rollupConfig = {
input: entry,
output: {
dir: 'es',
format: 'es',
entryFileNames: '[name].js',
exports: 'named',
},
plugins: [
clear({
targets: ['es'],
}),
resolve(),
commonjs({ include: 'node_modules/**' }),
babel({ exclude: 'node_modules/**', babelHelpers: 'bundled' }),
],
// 将模块视为外部模块,不会打包在库中
external: (id) => Object.keys(dependencies).some((e) => id.indexOf(e) === 0),
};
export default rollupConfig;
上述的2个文件,是关于ES模式打包的核心文件,内部逻辑也都相对比较好理解,和rollupConfig相关。
具体的其他配置可以网上搜索获取去官网查看。对于几个必要的我们说一下。
rollup.entry主要做为 打包的输入文件 input
输出的配置output,目录、格式化、文件名称等
exports 导出方式
外部模块 external 不会进行打包,主要读取package.json
"dependencies": {
"db.js": "^0.15.0", "fast-deep-equal": "^3.1.3", "js-cookie": "^2.2.1", "lodash": "^4.17.19", "moment": "^2.27.0", "socket.io-client": "1.4.5"
},
打包结果:
UMD打包
rollup.config.umd.js
// Rollup plugins
import babel from '@rollup/plugin-babel';
// 允许我们加载第三方模块
import resolve from '@rollup/plugin-node-resolve';
// 将它们转换为ES6版本
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import clear from 'rollup-plugin-clear';
import { uglify } from 'rollup-plugin-uglify';
import dependencies from './dependencies';
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
export default {
input: {
index: 'src/basic-utils/index.js',
},
output: {
dir: 'umd',
format: 'umd',
sourcemap: true,
entryFileNames: 'basic-utils.js',
exports: 'named',
name: 'EduBasicUtils',
globals: dependencies,
},
plugins: [
clear({
targets: ['umd'],
}),
resolve(),
commonjs({ include: 'node_modules/**' }),
babel({ exclude: 'node_modules/**' }),
replace({
exclude: 'node_modules/**',
ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
}),
process.env.NODE_ENV === 'production' && uglify(), //压缩仅支持es5
],
external: (id) => Object.keys(dependencies).some((e) => id === e),
};
dependencies.js
const dependencies = {
lodash: '_',
moment: 'moment',
'socket.io-client': 'io',
immer: 'immer',
'js-cookie': 'Cookies',
'db.js': 'db',
};
export default dependencies;
输入配置和输出配置和上面ES配置差不多。这块区别要注意的是
name: 'EduBasicUtils'
设置window下的全部变量访问方式。
打包结果:
其实区别还是比较大,umd方式会把所有的文件都打包压缩到一个文件中,对于第三方的包,可以进行选择性打包,也可以暴露引入方式。
应用场景不太一样
-
UMD方式更时候CDN方式应用,引入后会挂载到windows下
-
ES方式主要是export,所以项目中npm安装后,直接import直接使用
当然UMD方式导入到系统中,使用import也是可以的,只需要设置externals即可。
项目应用
index.html
<script type="text/javascript" src="<%= BASE_URL %>library/basic-utils.js"></script>
vue.config.js
externals设置
const dependencies = {
"db.js": "db",
'moment': 'moment',
'echarts': 'echarts',
"tinymce": "tinymce",
'lodash': '_',
"immer": 'immer',
'mqtt': 'mqtt',
'fetch-like-axios': 'axios',
'nprogress': 'NProgress',
'socket.io-client': 'io',
'@basic-utils': 'EduBasicUtils',
'js-cookie': 'Cookies',
"vue": 'Vue',
"vuex": 'Vuex',
'element-plus': 'ElementPlus',
'vue-router': 'VueRouter',
'hljs': 'hljs',
};
module.exports = dependencies
设计完毕~~~