浅谈应用设计-basic-utils工具库

350 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

设计思路:

对于项目开发来说,长期的积累,总结出一个常用的工具库,可能是每一个开发者心之所想的事情。

随着时间的流逝和经验的积累,会发现其实没有想象那么难

难就难在----

如何做起来?

为什么要做?

能提供什么有用的能力?

做之前需要思考一些问题:

  • 通用性
  • 扩展性
  • 简单好用

其实这几个要求,对设计来说,难度已经非常大了。

因为我们认为的不一定是我们认为的,随着经验的积累,认知只会推翻认知。

设计实践

image.png

看过之前的文章,大概对这张图理解可能不是很难,之前的服务层的很多设计都已讲解。我对工具库的定位,放在了框架层,为上层应用提供服务。

工具库目录

image.png

image.png

构建方式

使用 rollup 打包方式,支持umdes方式

打包完成后,发布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"

},

打包结果:

image.png

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下的全部变量访问方式。

打包结果:

image.png

其实区别还是比较大,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

设计完毕~~~