低代码平台(一)-远程组件打包(ESModule含源码和演示地址)

3,995 阅读2分钟

前言

最近的工作基本上在第三方低代码平台展开,使用过之后才发现低代码其实并不低代码,反而有种束手束脚的别扭感,很多时候业务设计的思路平台无法实现或者实现的体验感不佳。想写低代码文章的目的有两个,一个是熟悉低代码的逻辑和业务,二是想思考什么样的低代码平台才更被人想用。

localhost_5174_ (1).png

参考文章

技术栈

  • vue3 组件的开发语言,同时通过vue3的异步组件defineAsyncComponent来加载远程组件
  • vite 脚手架,用于调试组件
  • webpack 把组件编译打包成esm格式,并输出压缩文件

组件的目录结构

image.png

  • index.js 组件的入口文件
  • panel/index.js 组件配置面板的入口文件
  • card.json 组件配置项

card.json

{
    // 版本号
    "version": "1.0.2",
    // 默认显示的大小
    "config": {
        "width": 200,
        "height": 50
    },
    // 配置项
    "initProp": {
        "text": "我是一个文本组件",
        "textStyle": {
            "font": "",
            "fontSize": "12px"
        }
    }
    ...
}

后续随着功能的丰富,增加各种配置项。

使用vite初始化工程

yarn create vite 按照提示操作即可。
这一步就不赘述了,可查阅vite官网

webpack配置

安装webpack

依赖之间可能有版本要求,所以一开始最好跟我的版本一致。
yarn add webpack@5.89.0 webpack-cli@5.1.4 -D

完整配置

import { dirname} from "node:path"
import { fileURLToPath } from "node:url"
import { VueLoaderPlugin } from "vue-loader"
import FileManagerPlugin from 'filemanager-webpack-plugin'
import path from 'path'
import AutoImport from 'unplugin-auto-import/webpack'
import Components from 'unplugin-vue-components/webpack'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import CopyPlugin from 'copy-webpack-plugin'

// 打包命令
// npm run build:card --card=text
const getCurrentDir = () => {
  const __filename = fileURLToPath(import.meta.url)
  const __dirname = dirname(__filename)
  return __dirname
}
const __dirname = getCurrentDir()

const cardName = process.env.npm_config_card
const cardJson = await import(`../src/cards/${cardName}/card.json`,{ assert: {type: 'json'} })
const version = cardJson.default.version || '1.0.0'
const outputDir = `${cardName}-${version}`
export default {
  mode: "production",
  entry: {
    index: path.resolve(__dirname, `../src/cards/${cardName}/index.js`),
    panel: path.resolve(__dirname, `../src/cards/${cardName}/panel/index.js`)
  },
  // 兼容浏览器引入vue
  // 与加载组件的项目保持一致,使得远程组件和运行项目的vue上下文相同
  externals: {
    "vue": 'https://6c6f-lowcode-2gxh0baw4d19d595-1256670128.tcb.qcloud.la/assets/vue.esm.js'
  },
  output: {
    filename: "[name].js",
    path:  path.resolve(__dirname, `./dist`),
    library: { type: 'module' }
    // library: "MyPlugin",
    // libraryTarget: "umd",
  },
  experiments: { outputModule: true },
  plugins: [
    // 引入插件
    new VueLoaderPlugin(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
    new CopyPlugin({
      patterns: [
        { from: path.resolve(__dirname, `../src/cards/${cardName}/card.json`), to: path.resolve(__dirname, `./dist`) },
      ],
    }),
    new FileManagerPlugin({
      events: {
        onEnd: {
          delete: [
           path.resolve(__dirname, `./.zip/${outputDir}.zip`),
          ],
          archive: [
           {source: path.resolve(__dirname, `./dist`), destination: path.resolve(__dirname, `../.zip/${outputDir}.zip`)},
          ]
         }
      }
     })
  ],
  optimization: {
    minimize: true,
  },
  module: {
    rules: [
      // vue
      {
        test: /\.vue/,
        use: ["vue-loader"],
      },
      // JS
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              // 开始
              [
                "@babel/preset-env",
                {
                  useBuiltIns: "usage",
                  corejs: {
                    version: 3,
                  }
                },
              ],
              // 结束
            ],
          },
        },
      },
      // CSS
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      // Images
      {
        test: /\.(jpg|png|gif|svg)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              outputPath: "assets/images/",
            },
          },
        ],
      },

      // Fonts
      {
        test: /\.(ttf|eot|woff|woff2)$/,
        use: [
          {
            loader: "file-loader",
            options: {
              outputPath: "assets/fonts/",
            },
          },
        ]
      }
    ]
  }
}

打包命令

npm run build --card=组件名

具体文件目录可访问gitee地址

参考文章

其他文章