「前端」关闭源码依赖

问题背景

在 5.x 版本的 oinone 前端架构中,我们开放了部分源码,但是导致以下性能问题:

1.构建耗时增加​​:Webpack 需要编译源码文件

2.​​加载性能下降​​:页面需加载全部编译产物

3.​​冷启动缓慢​​:开发服务器启动时间延长

以下方案通过关闭源码依赖。

操作步骤

1. 添加路径修正脚本

1: 在当前项目工程根目录中的scripts目录添加patch-package-entry.js脚本,内容如下:

const fs = require('fs');
const path = require('path');

const targetPackages = [
  '@kunlun+vue-admin-base',
  '@kunlun+vue-admin-layout',
  '@kunlun+vue-router',
  '@kunlun+vue-ui',
  '@kunlun+vue-ui-antd',
  '@kunlun+vue-ui-common',
  '@kunlun+vue-ui-el',
  '@kunlun+vue-widget'
];

// 递归查找目标包的 package.json
function findPackageJson(rootDir, pkgName) {
  const entries = fs.readdirSync(rootDir);
  for (const entry of entries) {
    const entryPath = path.join(rootDir, entry);
    const stat = fs.statSync(entryPath);
    if (stat.isDirectory()) {
      if (entry.startsWith(pkgName)) {
        const [pkGroupName, name] = pkgName.split('+');
        const pkgDir = path.join(entryPath, 'node_modules', pkGroupName, name);
        const pkgJsonPath = path.join(pkgDir, 'package.json');
        if (fs.existsSync(pkgJsonPath)) {
          return pkgJsonPath;
        }
      }
      // 递归查找子目录
      const found = findPackageJson(entryPath, pkgName);
      if (found) return found;
    }
  }
  return null;
}

// 从 node_modules/.pnpm 开始查找
const pnpmDir = path.join(__dirname, '../', 'node_modules', '.pnpm');

for (const pkgName of targetPackages) {
  const packageJsonPath = findPackageJson(pnpmDir, pkgName);

  if (packageJsonPath) {
    try {
      const packageJSON = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
      if (packageJSON.main === 'index.ts') {
        const libName = packageJSON.name.replace('@', '').replace('/', '-');
        packageJSON.main = `dist/${libName}.esm.js`;
        packageJSON.module = `dist/${libName}.esm.js`;
        const typings = 'dist/types/index.d.ts';
        packageJSON.typings = typings;
        const [pwd] = packageJsonPath.split('package.json');
        const typingsUrl = path.resolve(pwd, typings);
        const dir = fs.existsSync(typingsUrl);
        if (!dir) {
          packageJSON.typings = 'dist/index.d.ts';
        }
        packageJSON.files = ['dist'];
        fs.writeFileSync(packageJsonPath, JSON.stringify(packageJSON, null, 2));
      }
    } catch (err) {
      process.exit(1);
    }
  }
}

2. 配置自动执行钩子

{
  "scripts": {
    "postinstall": "node ./scripts/patch-package-entry.js"
  }
}

脚本作用说明​​:postinstall 是 npm/pnpm 的生命周期钩子,会在每次执行 npm install 或 pnpm install 后自动触发,确保依赖更新后入口配置保持正确。

3. 重新安装依赖

pnpm install

Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/20960.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
汤乾华的头像汤乾华数式员工
上一篇 2025年4月17日 pm4:20
下一篇 2025年4月21日 am9:49

相关推荐

  • 表单页如何在服务端动作点击后让整个表单都处于loading状态

    介绍 在业务场景中,有时候由于提交的数据很多,导致服务端动作耗时较长,为了保证这个过程中表单内的字段不再能被编辑,我们可以通过自定义能力将整个表单区域处于loading状态 自定义动作组件代码 import { ActionType, ActionWidget, BaseElementViewWidget, BaseView, ClickResult, ServerActionWidget, SPI, Widget } from '@kunlun/dependencies'; @SPI.ClassFactory(ActionWidget.Token({ actionType: ActionType.Server })) class LoadingServerActionWidget extends ServerActionWidget { protected async clickAction(): Promise<ClickResult> { const baseView = Widget.select(this.rootHandle) as unknown as BaseView; if (!baseView) { return super.clickAction(); } const baseViewWidget = baseView.getChildrenInstance().find((a) => a instanceof BaseElementViewWidget) as unknown as BaseElementViewWidget; if (!baseViewWidget) { return super.clickAction(); } return new Promise((resolve, reject) => { try { baseViewWidget.load(async () => { const res = await super.clickAction(); resolve(res); }); } catch (e) { reject(false); } }); } } 本案例知识点 BaseElementWidget提供了load方法将继承了该class的元素渲染的区域做整体loading交互,等入参的函数处理完成后恢复正常状态,其实所有继承了ActionWidget的组件也提供了这个能力让按钮在执行函数中的时候处于loading状态, 每个组件都有一个全局唯一的handle值,所在根视图的rootHandle,组件可以用this.rootHandle通过Widget.Select方法查找到所在的根视图组件,从视图的实例化子元素里可以查找到具体的业务类型视图组件,如详情页的DetailWidget、表单页的FormWidget、表格页的TableWidget,拿到这些实例后就可以操作里面的属性和方法了

    2024年5月29日
    92800
  • 表格新增空行或者按照数据如何复制行

    场景 描述 新增按钮点击后表格出现空行,不带业务数据,需要有行内编辑 如何实现 第一步 在layout目录下新增copyTable组件,组件代码如下 import { BaseElementWidget, SPI, TableWidget, Widget } from '@kunlun/dependencies'; import { OioNotification } from '@kunlun/vue-ui-antd'; @SPI.ClassFactory(BaseElementWidget.Token({ widget: 'copy-table-row' })) export class CopyTableWidget extends TableWidget { @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB"), {}) private tableCopySub; @Widget.BehaviorSubContext(Symbol("$$TABLE_DELETE_CB")) private tableDeleteSub; @Widget.Reactive() @Widget.Provide() protected get editorMode(): any { return 'manual' } public async copyRowData(row,currentRow) { // 获取vxetable 实例 const tableRef = this.getTableInstance()!.getOrigin(); if (tableRef) { // 有复制未保存数据,如何处理? const insertData = tableRef.getInsertRecords(); if(insertData.length > 0){ OioNotification.warning("警告","请检查未保存数据!") return; } const { row: newRow } = await tableRef.insertAt(row,currentRow) // 插入一条数据并触发校验, 其中字段名称可以替换 await tableRef.setEditCell(newRow, 'city') } } public async deleteRowData(row) { // 获取vxetable 实例 const tableRef = this.getTableInstance()!.getOrigin(); if (tableRef) { // 有复制未保存数据,如何处理? console.log(row, 'remove row') tableRef.remove(row) // 插入一条数据并触发校验 } } async mounted() { super.mounted(); this.tableCopySub.subject.next({copyCb: (row,currentRow) => this.copyRowData(row,currentRow)}) this.tableDeleteSub.subject.next({deleteCb: (row) => this.deleteRowData(row)}) } } 第二步 在action目录下覆盖新增按钮或者复制行按钮;代码如下 import {ActionWidget, ClickResult, ReturnPromise, SPI, Widget} from "@kunlun/dependencies"; @SPI.ClassFactory( ActionWidget.Token({ model: 'resource.k2.Model0000001211', // 替换对应模型 name: 'uiView57c25f66fac9439089d590a4ac47f027' // 替换对应action的name }) ) export class CopyRow extends ActionWidget{ @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB")) private tableCopySub; private tableCopyCb; @Widget.Method() public clickAction(): ReturnPromise<ClickResult> { // 按照某一条数据复制行, 按钮在行内 // let data = JSON.parse(JSON.stringify(this.activeRecords?.[0])); // 复制行删除id // if(data) { // delete…

    2024年7月15日
    1.1K00
  • 表格如何支持表尾合计计算

    介绍 可以通过扩展TableWidget.ts实现 示例代码 import { BaseElementWidget, DslDefinitionType, SPI, TableWidget, ViewType, Widget } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ type: ViewType.Table, widget: 'table', model: 'resource.k2.Model0000000109', viewName: '移动端品牌_TABLE_0000000000021513' }) ) export class FooterStatisticsTable extends TableWidget { public initialize(props) { if (props.template) { props.template?.widgets?.forEach((a) => { if (a.dslNodeType === DslDefinitionType.FIELD && this.statisticsFieldList.includes(a.name)) { a.statistics = true; } }); } super.initialize(props); return this; } // 需要表尾做合并的字段名称 public statisticsFieldList = ['fansNum']; @Widget.Reactive() protected get showFooter(): boolean | undefined { return true; } } 效果预览

    2024年10月14日
    86300
  • 前端打包文件上传到oss

    打包dist文件上传到oss教程 1: 确保boot工程里面安装了「webpack-aliyun-oss」依赖, 如果没有安装,可以手动安装下 2: package.json -> devDependencies -> {"webpack-aliyun-oss": "0.5.2"} 3: 在vue.config.js文件中添加对应的plugin // vue.config.js文件 // 新增代码 let BASE_URL = '/'; const { DEPLOY, OSS_REGION, OSS_DIST, OSS_URL, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, OSS_BUCKET } = process.env; const UNIQUE_KEY = Math.random(); switch (DEPLOY) { case 'online': BASE_URL = `${OSS_URL}${UNIQUE_KEY}/`; break; default: BASE_URL = '/'; } module.exports = { …原先的代码, publicPath: BASE_URL, plugins: [ …原先的插件, DEPLOY === 'online' ? new WebpackAliyunOss({ from: ['./dist/**/**', '!./dist/**/*.html'], // build目录下除html之外的所有文件 dist: `${OSS_DIST}/${UNIQUE_KEY}`, // oss上传目录 region: OSS_REGION, // 地区, 比如 oss-cn-hangzhou accessKeyId: OSS_ACCESS_KEY_ID, accessKeySecret: OSS_ACCESS_KEY_SECRET, bucket: OSS_BUCKET, timeout: 1200000, deleteOrigin: true, deleteEmptyDir: true, overwrite: true }) : () => {} ] } 4: 在vue.config.js同级目录下面新增「.env」文件, 写入对应的配置, 配置对应的值按照自己的oss配置来 DEPLOY=online OSS_BUCKET=xxx OSS_DIST=/oinone/product OSS_URL=https://xxxxxx/oinone/product/ OSS_REGION=oss-cn-hangzhou OSS_ACCESS_KEY_ID=xxxx OSS_ACCESS_KEY_SECRET=xxxx

    2023年11月1日
    81100
  • oio-spin 加载中

    用于页面和区块的加载中状态。 何时使用 页面局部处于等待异步数据或正在渲染过程时,合适的加载动效会有效缓解用户的焦虑。 API 参数 说明 类型 默认值 版本 delay 延迟显示加载效果的时间(防止闪烁) number (毫秒) – loading 是否为加载中状态 boolean true wrapperClassName 包装器的类属性 string –

    2023年12月18日
    71100

Leave a Reply

登录后才能评论