跳到主要内容

开发与适配

CloudBase CMS 基于 qiankun 实现了微应用加载能力,已有的项目经过简单的配置修改,即可适配为微应用。

同时,我们也提供了 Vue 和 React 的微应用开发模版,提供快速开发使用,你可以通过 CloudBase CLI 直接下载模版。

# 新建 React 微应用项目tcb new react-app cms-microapp-react
# 新建 Vue 微应用项目tcb new vue-app cms-microapp-vue

React 项目适配#

1. 路由适配#

设置 hash 模式路由的 basename/project/microapp/${microAppID}/,其中 ${microApp} 为你创建的微应用的 AppID

目前,CloudBase CMS 仅支持 hash 模式的路由

<HashRouter basename={`/project/microapp/${microAppID}/`}>

2. 入口修改#

修改 index.js入口文件,为了避免根 id #root 与其他的 DOM 冲突,需要限制查找范围

import React from "react";import ReactDOM from "react-dom";import App from "./App";
function render(props) {  const { container } = props;  ReactDOM.render(    <App />,    container ? container.querySelector("#root") : document.querySelector("#root")  );}
if (!window.__POWERED_BY_QIANKUN__) {  render({});}
export async function bootstrap() {  console.log("[react16] react app bootstraped");}
export async function mount(props) {  console.log("[react16] props from main framework", props);  render(props);}
export async function unmount(props) {  const { container } = props;  ReactDOM.unmountComponentAtNode(    container ? container.querySelector("#root") : document.querySelector("#root")  );}

3. 构建配置修改#

修改 Webpack 配置,需要修改 output 配置以及 publicPath/cloudbase-cms/apps/${microAppID}/,其中 ${microApp} 为你创建的微应用的 AppID

// 微应用 APPIDconst microAppID = "reactApp";
module.exports = {  webpack: (config) => {    // 微应用的包名,这里与主应用中注册的微应用名称一致    config.output.library = `${microAppID}`;    // 将你的 library 暴露为所有的模块定义下都可运行的方式    config.output.libraryTarget = "umd";    // 按需加载相关,设置为 webpackJsonp_react-project 即可    config.output.jsonpFunction = `webpackJsonp_${microAppID}`;
    // 修改 publicPath    if (process.env.NODE_ENV === "production") {      config.output.publicPath = `/cloudbase-cms/apps/${microAppID}/`;    }    return config;  }};

Vue 项目适配#

以 Vue CLI 生成的 Vue 2.x 项目为例

1. 入口文件修改#

入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围

import Vue from "vue";import App from "./App.vue";
Vue.config.productionTip = false;
let instance = null;const isDev = process.env.NODE_ENV === "development";
function render(props = {}) {  const { container } = props;
  instance = new Vue({    render: (h) => h(App)  }).$mount(container ? container.querySelector("#app") : "#app");}
// 独立运行时if (isDev || !window.__POWERED_BY_QIANKUN__) {  render();}
export async function bootstrap() {  console.log("[vue] vue app bootstraped");}
export async function mount(props) {  console.log("[vue] props from main framework", props);  render(props);}
export async function unmount() {  instance.$destroy();  instance.$el.innerHTML = "";  instance = null;}

2. 构建配置修改#

打包配置修改(vue.config.js),修改 output 配置,以及设置publicPath/cloudbase-cms/apps/${microAppID}/,其中 ${microApp} 为你创建的微应用的 AppID

// CMS 微应用 APPIDconst microAppID = "vueApp";const isDev = process.env.NODE_ENV === "development";
module.exports = {  publicPath: isDev ? "/" : `/cloudbase-cms/apps/${microAppID}/`,  devServer: {    headers: {      "Access-Control-Allow-Origin": "*"    }  },  configureWebpack: {    output: {      library: `${microAppID}`,      libraryTarget: "umd", // 把微应用打包成 umd 库格式      jsonpFunction: `webpackJsonp_${microAppID}`    }  }};

注意,由于 Vue Hash 模式的问题,目前 CloudBase CMS 微应用还无法支持 Vue 路由的使用

非 Webpack 构建的微应用#

一些非 webpack 构建的项目,例如 jQuery 项目、jsp 项目,都可以按照这个处理。

接入之前请确保你的项目里的图片、音视频等资源能正常加载,如果这些资源的地址都是完整路径(例如 https://docs.cloudbase.net/logo.png),则没问题。如果都是相对路径,需要先将这些资源上传到服务器,使用完整路径。

接入非常简单,只需要额外声明一个 script,用于 export 相对应的 lifecycles。例如:

1. 声明 entry 入口#

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <title>Purehtml Example</title>  </head>  <body>    <div>Purehtml Example</div>  </body>  <script src="//yourhost/entry.js" entry></script></html>

2. 在 entry.js 里声明 lifecycles#

const render = ($) => {  $("#purehtml-container").html("Hello, render with jQuery");  return Promise.resolve();};
((global) => {  global["purehtml"] = {    bootstrap: () => {      console.log("purehtml bootstrap");      return Promise.resolve();    },    mount: () => {      console.log("purehtml mount");      return render($);    },    unmount: () => {      console.log("purehtml unmount");      return Promise.resolve();    }  };})(window);