Malagu 框架提供了一个命令行工具 @malagu/cli ,该工具提供了一些基础的命令,帮助我们初始化、运行、构建和部署项目。该工具只包含最核心的功能,通过命令行插件机制把一些非核心的功能不同平台部署逻辑通过插件的方式提供,命令行插件也是组件的一种形式。通过插件机制,我们可以为命令行工具添加新的命令,或者扩展老的命令。在 Malagu 框架中,很多地方都使用到了命令行插件。

安装

命令行工具除了 malagu init 命令意外,其他命令都会委托给当前项目中的 @malagu/service 执行,无需担心全局命令与项目本地命令版本不一致问题。命令行工具基于 npm 和 yarn 进行包的管理,命令行会基于当前项目的环境情况智能选择合适的包管理工具,如果 npm 和 yarn 都满足条件,则优先选择使用 yarn 工具。例如:当项目根目录下存在 yarn.lock 文件,则使用 yarn。当然,我们也可以强行指定包管理器,使用配置属性: malagu.packager

  1. # 指定淘宝镜像源下载会更快
  2. npm install -g @malagu/cli --registry https://registry.npm.taobao.org

命令行说明

我们可以通过 malagu -h 命令查看命令行帮助信息,malagu -h 命令如下:

  1. Usage: malagu <command> [options]
  2. Malagu CLI 0.0.44
  3. Options:
  4. -V, --version output the version number
  5. -h, --help output usage information
  6. Commands:
  7. init [options] [name] [template] init a application
  8. serve [options] [entry] serve a applicaton
  9. build [options] [entry] build a application
  10. deploy [options] [entry] deploy a applicaton
  11. config config faas adapter profile

主要包含四个核心命令:

  1. malagu init:初始化一个模板应用
  2. malagu serve:本地运行应用
  3. malgu build:构建应用,一般情况不使用,部署应用的时候自动使用该命令构建项目
  4. malagu deploy:部署应用,通过 -s, --skip-build 选项跳过构建过程
  5. malagu config:配置 FaaS 适配器相关的个性信息,例如 AKSK,region 等等。该命令是一个上下文命令,只要满足一定上下文要求才会看到该命令,所有需要在项目根目录执行该命令,并且项目依赖了 FaaS 适配器相关的组件,例如 fc-adapterscf-adapter 等等。

初始化

我们可以通过 malagu init 命令使用模板,malagu init 命令如下:

  1. Usage: malagu init [options] [name] [template]
  2. init a application
  3. Options:
  4. -o, --output-dir [path] output directory (default: ".")
  5. -h, --help output usage information

参数:

  • name 应用名称,可选,如果没有指定应用名称,则使用模板名称作为应用名称
  • tempate 应用模板,可选,支持指定内置模板名称和 GitHub Repository 地址。如果指定 template 参数,则必须指定应用名称;如果没有指定 template 参数,命令行会提示我们从内置模板中选择一个

选项:

  • -o,--output-dir 应用输出的位置,可选,如果不指定该选项,则输出位置为命令行执行时的工作目录

示例:

  1. # 不指定名称,从内置模板列表中选择
  2. $ malagu init
  3. # 指定名称,从内置模板列表中选择
  4. $ malagu init demo
  5. # 指定模板为内置模板名称
  6. $ malagu init demo backend-app
  7. # 指定模板为 GitHub Repository 地址
  8. $ malagu init demo git@github.com:cellbang/cellbang-site.git # 或者 malagu init demo https://github.com/cellbang/cellbang-site.git

内置模板

  • sample-app:前后端一体化应用,前后端通信使用 RPC 风格
  • backend-app:后端应用,使用 REST 风格暴露 API 接口
  • vue-app:使用 vue 作为前端的前后端一体化应用
  • database-app:访问数据库应用,配置好数据库链接,使用 typeorm 操作数据库
  • accounts:账号中心,配置好数据库和 github 等第三方 oauth 凭证即可完成一个真实场景的第三方认证与授权
  • schedule:定时任务调度应用,支持 Serverless 场景,屏蔽不同 Serverless 平台之间的差异,一键部署
  • admin-app:前后端一体化应用,前后端通信使用 RPC 风格,后端管理系统模板
  • microservice:微服务应用
  • file-service:基于对象存储服务的文件服务应用
  • puppeteer:无头浏览器应用
  • monorepo:monorepo 项目风格应用,将一个大项目拆分成多个 Malagu 组件
  • mycli:命令行应用,快速开发命令行工具 ```bash
    1. ___
    /‘_/\ /\_ \ /\ \ __ \//\ \ __ __ __ __ \ \ \__\ \ /'__\ \ \ \ /‘\ /'_\/\ \/\ \ \ \ _/\ \/\ \L._ _\ _/\ \L._/\ \L\ \ \ _\ \ \ _\ _\ \/._\/__\ \/._\ _ \ _/ \// \//\//\//\/_/\//\//\/L\ \/_/
    1. /\____/
    2. @malagu/cli@1.18.0 \_/__/

? Select a template to init (Use arrow keys or type to search) ❯ backend-app Official sample-app Official vue-app Official database-app Official admin-app Official microservice Official file-service Official puppeteer Official monorepo Official mycli Official

  1. <a name="Jli2K"></a>
  2. ## 本地运行
  3. 我们可以通过 `malagu serve` 命令本地运行项目,推荐使用 `npx malagu serve` 运行项目,`malagu serve` 命令如下:
  4. ```bash
  5. Usage: serve [options] [entry]
  6. serve a applicaton
  7. Options:
  8. -o, --open [open] Open browser
  9. -p, --port [port] Port used by the server
  10. -t, --targets [targets] Specify application targets
  11. -m, --mode [mode] Specify application mode
  12. -h, --help output usage information

参数:

  • entry 应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件

选项:

  • -o,--open 启动完成后自动打开浏览器访问应用服务地址,可选,默认不打开浏览器
  • -p,--port 应用服务启动的端口号,可选,默认 3000
  • -t,--targets 应用构建目标产物,可选,默认值是 ['frontend', 'backend']
  • -m,--mode 应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启 local 模式

示例:

  1. # 指定端口号和打开浏览器
  2. $ malagu serve -p 30001 -o
  3. # 指定应用构建目标产物
  4. $ malagu serve -t frontend
  5. # 指定单个应用运行模式
  6. $ malagu serve -m test
  7. # 指定多个应用运行模式
  8. $ malagu serve -m cdn,database # 或者 malagu serve -m cdn -m database

构建

我们可以通过 malagu build 命令构建项目,推荐使用 npx malagu build 构建项目,malagu build 命令如下:

  1. Usage: build [options] [entry]
  2. build a application
  3. Options:
  4. -t, --targets [targets] Specify application targets (default: [])
  5. -m, --mode [mode] Specify application mode (default: [])
  6. -p, --prod [prod] Create a production build
  7. -h, --help output usage information

参数:

  • entry 应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件

选项:

  • -t,--targets 应用构建目标产物,可选,默认值是 ['frontend', 'backend']
  • -m,--mode 应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启 remote 模式
  • -p,--prod 生产环境标识,可选,简化生产环境构建命令

示例:

  1. # 指定应用构建目标产物
  2. $ malagu build -t frontend
  3. # 指定单个应用运行模式
  4. $ malagu build -m test
  5. # 指定多个应用运行模式
  6. $ malagu build -m cdn,database # 或者 malagu serve demo -m cdn -m database
  7. # 指定生产环境标识
  8. $ malagu build -p

注意:一般情况,不需要手动执行构建命令,因为在执行部署命令的时候会自动构建,部署命令可以通过选项 -s, --skip-build 跳过构建过程。如果你不打算使用框架提供的部署命令,此时,你需要自己手动执行构建命令。不过,当框架提供的部署命令不满足你的业务需要,更推荐的做法是通过提供一个命令 [Deploy](#0ji38) 插件,自定义部署逻辑。

部署

我们可以通过 malagu build 命令部署项目,使用部署命令前,需要安装对应平台的适配器组件,比如 @malagu/fc-adapter@malagu/scf-adapter 等等。推荐使用 npx malagu deploy 部署项目,malagu deploy 命令如下:

  1. Usage: deploy [options] [entry]
  2. deploy a applicaton
  3. Options:
  4. -t, --targets [targets] Specify application targets (default: [])
  5. -m, --mode [mode] Specify application mode (default: [])
  6. -p, --prod [prod] Create a production deployment
  7. -s, --skip-build [skipBuild] Skip the build process
  8. -h, --help

参数:

  • entry 应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件

选项:

  • -t,--targets 应用构建目标产物,可选,默认值是 ['frontend', 'backend']
  • -m,--mode 应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启 remote 模式
  • -p,--prod 生产环境标识,可选,简化生产环境构建命令
  • -s,--skip-build 跳过构建过程,可选,默认不跳过,部署的时候,构建过程没有问题,但是部署出现了网络问题,这个时候,可以跳过构建过程直接部署

示例:

  1. # 指定应用构建目标产物
  2. $ malagu deploy -t frontend
  3. # 指定单个应用运行模式
  4. $ malagu deploy -m test
  5. # 指定多个应用运行模式
  6. $ malagu deploy -m cdn,database # 或者 malagu serve demo -m cdn -m database
  7. # 指定生产环境标识
  8. $ malagu deploy -p
  9. # 跳过构建过程
  10. $ malagu deploy -s

插件

命令行工具包含最核心的功能,通过命令行插件机制把一些非核心的功能不同平台部署逻辑通过插件的方式提供,命令行插件也是组件的一种形式。通过插件机制,我们可以为命令行工具添加新的命令,或者扩展老的命令。在 Malagu 框架中,很多地方都使用到了命令行插件。

Cli 插件

执行 malagu 命令的时候,执行该插件。通过 Cli 插件,我们可以为命令行工具添加新的命令,或者扩展老的命令,这是一个自由度非常高的一个插件,比如使用 Cli 插件添加一个新命令:

  1. import { CliContext } from '@malagu/cli-service';
  2. export default async (context: CliContext) => {
  3. const { program } = context;
  4. program
  5. .command('login')
  6. .description('Sign in to the app')
  7. .action(() => {
  8. console.log('login');
  9. });
  10. }

插件代码存放到项目目录 src/cli-hook.ts 或者 src/hooks/cli.ts ,框架自动识别加载,也可以通过属性 cliHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息,执行不同命令,参数是不一样的,该上下文也会把命令的参数放进来,例如 Serve 插件的上下文中,包含了 portopendev 等信息

Webpack 插件

执行 malagu 命令需要 Webpack 构建的时候,执行该插件。通过 Webpack 插件,我们可以自定义 Webpack 构建行为,我们也可以通过 malagu.webpack 属性配置 Webpack,但是,对于一些自由度比较高的配置,Webpack 插件方式更加适合 。比如使用 Webpack 插件添加一个 Webpack 自己的插件:

  1. import { WebpackContext, ConfigurationContext } from '@malagu/cli-service';
  2. export default async (context: WebpackContext) => {
  3. const { configurations } = context;
  4. const config = ConfigurationContext.getFrontendConfiguration(configurations);
  5. if (config) {
  6. const { VueLoaderPlugin } = require('vue-loader');
  7. config
  8. .module
  9. .rule('vue')
  10. .test(/\.vue$/)
  11. .use('vue-loader')
  12. .loader('vue-loader')
  13. .end()
  14. .end()
  15. .rule('css')
  16. .test(/\.css$/)
  17. .use('vue-style-loader')
  18. .loader('vue-style-loader')
  19. .end()
  20. .use('css-loader')
  21. .loader('css-loader');
  22. config
  23. .plugin('vueLoader')
  24. .use(VueLoaderPlugin);
  25. }
  26. };

插件代码存放到项目目录 src/webpack-hook.ts 或者 src/hooks/webpack.ts ,框架自动识别加载,也可以通过属性 webpackHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • configurations Webpack 配置对象,与 getWebpackConfig 不同,getWebpackConfig 获取的是组件属性中的 malagu.webpack
  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息, 包含了 prodmodetargetsdeventry 等信息

Deploy 插件

执行 malagu deploy 命令的时候,执行该插件。通过 Deploy 插件,我们可以自定义部署行为。比如使用 Deploy 插件实现项目部署到函数计算平台:

  1. export default async (context: DeployContext) => {
  2. const { cfg } = context;
  3. const deployConfig = getMalaguConfig(cfg, BACKEND_TARGET)['faas-adapter'];
  4. const profileProvider = new ProfileProvider();
  5. profile = {
  6. ...await profileProvider.provide(),
  7. ...deployConfig.profile
  8. };
  9. const regions = deployConfig.regions || [profile.defaultRegion];
  10. for (region of regions) {
  11. await doDeploy(context, deployConfig);
  12. }
  13. };

插件代码存放到项目目录 src/deploy-hook.ts 或者 src/hooks/deploy.ts ,框架自动识别加载,也可以通过属性 deployHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • configurations Webpack 配置对象,与 getWebpackConfig 不同,getWebpackConfig 获取的是组件属性中的 malagu.webpack
  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息, 包含了 prodmodetargetsdeventry 等信息

Build 插件

执行 malagu build 命令的时候,执行该插件。通过 Build 插件,我们可以自定义构建行为。比如使用 Build 插件实现项目为部署到函数计算平台 custom 运行时,而生成 bootstrap 启动文件:

  1. import { BuildContext, getHomePath } from '@malagu/cli-service';
  2. import { join } from 'path';
  3. import { writeFile } from 'fs-extra';
  4. import { FaaSAdapterUtils } from '@malagu/faas-adapter/lib/hooks';
  5. export default async (context: BuildContext) => {
  6. const { pkg, cfg } = context;
  7. const adapterConfig = FaaSAdapterUtils.getConfiguration<any>(cfg);
  8. if (adapterConfig.type === 'custom') {
  9. const destDir = join(getHomePath(pkg), 'bootstrap');
  10. const bootstrap = adapterConfig.function.bootstrap;
  11. delete adapterConfig.function.bootstrap;
  12. await writeFile(destDir, `#!/bin/bash\n${bootstrap}`, { mode: 0o755 });
  13. }
  14. };

插件代码存放到项目目录 src/build-hook.ts 或者 src/hooks/build.ts ,框架自动识别加载,也可以通过属性 buildHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • configurations Webpack 配置对象,与 getWebpackConfig 不同,getWebpackConfig 获取的是组件属性中的 malagu.webpack
  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息, 包含了 prodmodetargetsdeventry 等信息

Serve 插件

执行 malagu serve 命令的时候,执行该插件。通过 Serve 插件,我们可以自定义本地运行行为。比如使用 Serve 插件实现基于 Webpack Dev Server 的本地运行:

  1. import { ServeContext } from '@malagu/cli-service';
  2. import * as express from 'express';
  3. export class Deferred<T> {
  4. resolve: (value?: T) => void;
  5. reject: (err?: any) => void; // tslint:disable-line
  6. promise = new Promise<T>((resolve, reject) => {
  7. this.resolve = resolve;
  8. this.reject = reject;
  9. });
  10. }
  11. export default async (context: ServeContext) => {
  12. const { app, entryContextProvider } = context;
  13. app.use(express.json());
  14. app.use(express.raw());
  15. app.use(express.text());
  16. app.use(express.urlencoded({ extended: true }));
  17. let doDispatch: (req: any, res: any) => void;
  18. const compileDeferred = new Deferred<void>();
  19. context.compiler.hooks.done.tap('WebServe', () => {
  20. entryContextProvider().then(async (ctx: any) => {
  21. const { Dispatcher, Context, HttpContext, ContainerProvider, Application, container } = ctx;
  22. const c = await container;
  23. ContainerProvider.set(c);
  24. await c.get(Application).start();
  25. const dispatcher = c.get(Dispatcher);
  26. doDispatch = (req: any, res: any) => {
  27. const httpContext = new HttpContext(req, res);
  28. Context.run(() => dispatcher.dispatch(httpContext));
  29. };
  30. compileDeferred.resolve();
  31. });
  32. });
  33. app.all('*', async (req: any, res: any) => {
  34. await compileDeferred.promise;
  35. doDispatch(req, res);
  36. });
  37. };

插件代码存放到项目目录 src/serve-hook.ts 或者 src/hooks/serve.ts ,框架自动识别加载,也可以通过属性 serveHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • server http 的 Server 对象
  • app 基础框架应用对象,例如 Express 的 Application 对象
  • compiler Webpack 的编译对象
  • entryContextProvider 通过入口文件提供上下文的方法,通过该异步方法可以获取启动 Malagu 应用需要的上下文
  • configurations Webpack 配置对象,与 getWebpackConfig 不同,getWebpackConfig 获取的是组件属性中的 malagu.webpack
  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息,包含了 portopendev 等信息

Config 插件

框架在应用配置计算表达式之前,执行该插件。通过 Config 插件,我们可以动态添加一些特殊的应用配置。比如使用 Config 插件为应用配置动态添加阿里云账号 ID:

  1. import { ConfigContext } from '@malagu/cli-service';
  2. import { DefaultProfileProvider, FaaSAdapterUtils, FaaSAdapterConfiguration } from '@malagu/faas-adapter/lib/hooks';
  3. export default async (context: ConfigContext) => {
  4. const { config, cfg } = context;
  5. if (config.mode && config.mode.includes('remote')) {
  6. context.spinner?.stop();
  7. const adapterConfig = FaaSAdapterUtils.getConfiguration<FaaSAdapterConfiguration>(cfg);
  8. const profileProvider = new DefaultProfileProvider();
  9. const profile = await profileProvider.provide(adapterConfig);
  10. const faasAdapter = config.malagu['faas-adapter'];
  11. if (!faasAdapter.account?.id) {
  12. faasAdapter.account = profile.account;
  13. }
  14. if (!faasAdapter.region) {
  15. faasAdapter.region = profile.region;
  16. }
  17. }
  18. };

插件代码存放到项目目录 src/config-hook.ts 或者 src/hooks/config.ts ,框架自动识别加载,也可以通过属性 configHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • config 应用配置对象
  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置

Init 插件

执行 malagu init 命令的时候,执行该插件。比如:

  1. import { InitContext } from '@malagu/cli';
  2. export default async (context: InitContext) => {
  3. ...
  4. };

插件代码存放到项目目录 src/init-hook.ts 或者 src/hooks/init.ts ,框架自动识别加载,也可以通过属性 initHooks 自定义其他目录位置。

通过命令行上下文,我们可以取到一下相关信息:

  • program 命令行对象,通过该对象可以获取命令相关信息
  • pkg 应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息
  • cfg 应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:
    • getConfig 根据 target 获取前端或者后端配置
    • getMalaguConfig 根据 target 获取前端或者后端 malagu 配置
    • getWebpackConfig 根据 target 获取前端或者后端 webpack 配置
  • 其他信息,包含了 nametempateoutputDir 等信息