Malagu 框架提供了一个命令行工具 @malagu/cli ,该工具提供了一些基础的命令,帮助我们初始化、运行、构建和部署项目。该工具只包含最核心的功能,通过命令行插件机制把一些非核心的功能、不同平台部署逻辑通过插件的方式提供,命令行插件也是组件的一种形式。通过插件机制,我们可以为命令行工具添加新的命令,或者扩展老的命令。在 Malagu 框架中,很多地方都使用到了命令行插件。
安装
命令行工具除了 malagu init 命令意外,其他命令都会委托给当前项目中的 @malagu/service 执行,无需担心全局命令与项目本地命令版本不一致问题。命令行工具基于 npm 和 yarn 进行包的管理,命令行会基于当前项目的环境情况智能选择合适的包管理工具,如果 npm 和 yarn 都满足条件,则优先选择使用 yarn 工具。例如:当项目根目录下存在 yarn.lock 文件,则使用 yarn。当然,我们也可以强行指定包管理器,使用配置属性: malagu.packager 。
# 指定淘宝镜像源下载会更快npm install -g @malagu/cli --registry https://registry.npm.taobao.org
命令行说明
我们可以通过 malagu -h 命令查看命令行帮助信息,malagu -h 命令如下:
Usage: malagu <command> [options]Malagu CLI 0.0.44Options:-V, --version output the version number-h, --help output usage informationCommands:init [options] [name] [template] init a applicationserve [options] [entry] serve a applicatonbuild [options] [entry] build a applicationdeploy [options] [entry] deploy a applicatonconfig config faas adapter profile
主要包含四个核心命令:
- malagu init:初始化一个模板应用
- malagu serve:本地运行应用
- malgu build:构建应用,一般情况不使用,部署应用的时候自动使用该命令构建项目
- malagu deploy:部署应用,通过
-s, --skip-build选项跳过构建过程 - malagu config:配置 FaaS 适配器相关的个性信息,例如 AKSK,region 等等。该命令是一个上下文命令,只要满足一定上下文要求才会看到该命令,所有需要在项目根目录执行该命令,并且项目依赖了 FaaS 适配器相关的组件,例如
fc-adapter、scf-adapter等等。
初始化
我们可以通过 malagu init 命令使用模板,malagu init 命令如下:
Usage: malagu init [options] [name] [template]init a applicationOptions:-o, --output-dir [path] output directory (default: ".")-h, --help output usage information
参数:
name应用名称,可选,如果没有指定应用名称,则使用模板名称作为应用名称tempate应用模板,可选,支持指定内置模板名称和 GitHub Repository 地址。如果指定template参数,则必须指定应用名称;如果没有指定template参数,命令行会提示我们从内置模板中选择一个
选项:
-o,--output-dir应用输出的位置,可选,如果不指定该选项,则输出位置为命令行执行时的工作目录
示例:
# 不指定名称,从内置模板列表中选择$ malagu init# 指定名称,从内置模板列表中选择$ malagu init demo# 指定模板为内置模板名称$ malagu init demo backend-app# 指定模板为 GitHub Repository 地址$ 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
/‘_/___
\ /\_ \ /\ \ __ \//\ \ __ __ __ __ \ \ \__\ \ /'__\ \ \ \ /‘\ /'_\/\ \/\ \ \ \ _/\ \/\ \L._ _\ _/\ \L._/\ \L\ \ \ _\ \ \ _\ _\ \/._\/__\ \/._\ _ \ _/ \// \//\//\//\/_/\//\//\/L\ \/_//\____/@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
<a name="Jli2K"></a>## 本地运行我们可以通过 `malagu serve` 命令本地运行项目,推荐使用 `npx malagu serve` 运行项目,`malagu serve` 命令如下:```bashUsage: serve [options] [entry]serve a applicatonOptions:-o, --open [open] Open browser-p, --port [port] Port used by the server-t, --targets [targets] Specify application targets-m, --mode [mode] Specify application mode-h, --help output usage information
参数:
entry应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件
选项:
-o,--open启动完成后自动打开浏览器访问应用服务地址,可选,默认不打开浏览器-p,--port应用服务启动的端口号,可选,默认 3000-t,--targets应用构建目标产物,可选,默认值是['frontend', 'backend']-m,--mode应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启local模式
示例:
# 指定端口号和打开浏览器$ malagu serve -p 30001 -o# 指定应用构建目标产物$ malagu serve -t frontend# 指定单个应用运行模式$ malagu serve -m test# 指定多个应用运行模式$ malagu serve -m cdn,database # 或者 malagu serve -m cdn -m database
构建
我们可以通过 malagu build 命令构建项目,推荐使用 npx malagu build 构建项目,malagu build 命令如下:
Usage: build [options] [entry]build a applicationOptions:-t, --targets [targets] Specify application targets (default: [])-m, --mode [mode] Specify application mode (default: [])-p, --prod [prod] Create a production build-h, --help output usage information
参数:
entry应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件
选项:
-t,--targets应用构建目标产物,可选,默认值是['frontend', 'backend']-m,--mode应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启remote模式-p,--prod生产环境标识,可选,简化生产环境构建命令
示例:
# 指定应用构建目标产物$ malagu build -t frontend# 指定单个应用运行模式$ malagu build -m test# 指定多个应用运行模式$ malagu build -m cdn,database # 或者 malagu serve demo -m cdn -m database# 指定生产环境标识$ malagu build -p
注意:一般情况,不需要手动执行构建命令,因为在执行部署命令的时候会自动构建,部署命令可以通过选项 -s, --skip-build 跳过构建过程。如果你不打算使用框架提供的部署命令,此时,你需要自己手动执行构建命令。不过,当框架提供的部署命令不满足你的业务需要,更推荐的做法是通过提供一个命令 [Deploy](#0ji38) 插件,自定义部署逻辑。
部署
我们可以通过 malagu build 命令部署项目,使用部署命令前,需要安装对应平台的适配器组件,比如 @malagu/fc-adapter 、 @malagu/scf-adapter 等等。推荐使用 npx malagu deploy 部署项目,malagu deploy 命令如下:
Usage: deploy [options] [entry]deploy a applicatonOptions:-t, --targets [targets] Specify application targets (default: [])-m, --mode [mode] Specify application mode (default: [])-p, --prod [prod] Create a production deployment-s, --skip-build [skipBuild] Skip the build process-h, --help
参数:
entry应用入口文件,可选,一般不需要指定,框架根据当前项目组件依赖情况自动选择合适的应用入口文件
选项:
-t,--targets应用构建目标产物,可选,默认值是['frontend', 'backend']-m,--mode应用运行模式,可选,框架根据指定模式加载对应的模式配置件,本命令默认开启remote模式-p,--prod生产环境标识,可选,简化生产环境构建命令-s,--skip-build跳过构建过程,可选,默认不跳过,部署的时候,构建过程没有问题,但是部署出现了网络问题,这个时候,可以跳过构建过程直接部署
示例:
# 指定应用构建目标产物$ malagu deploy -t frontend# 指定单个应用运行模式$ malagu deploy -m test# 指定多个应用运行模式$ malagu deploy -m cdn,database # 或者 malagu serve demo -m cdn -m database# 指定生产环境标识$ malagu deploy -p# 跳过构建过程$ malagu deploy -s
插件
命令行工具包含最核心的功能,通过命令行插件机制把一些非核心的功能、不同平台部署逻辑通过插件的方式提供,命令行插件也是组件的一种形式。通过插件机制,我们可以为命令行工具添加新的命令,或者扩展老的命令。在 Malagu 框架中,很多地方都使用到了命令行插件。
Cli 插件
执行 malagu 命令的时候,执行该插件。通过 Cli 插件,我们可以为命令行工具添加新的命令,或者扩展老的命令,这是一个自由度非常高的一个插件,比如使用 Cli 插件添加一个新命令:
import { CliContext } from '@malagu/cli-service';export default async (context: CliContext) => {const { program } = context;program.command('login').description('Sign in to the app').action(() => {console.log('login');});}
插件代码存放到项目目录 src/cli-hook.ts 或者 src/hooks/cli.ts ,框架自动识别加载,也可以通过属性 cliHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
program命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息,执行不同命令,参数是不一样的,该上下文也会把命令的参数放进来,例如
Serve插件的上下文中,包含了port、open、dev等信息
Webpack 插件
执行 malagu 命令需要 Webpack 构建的时候,执行该插件。通过 Webpack 插件,我们可以自定义 Webpack 构建行为,我们也可以通过 malagu.webpack 属性配置 Webpack,但是,对于一些自由度比较高的配置,Webpack 插件方式更加适合 。比如使用 Webpack 插件添加一个 Webpack 自己的插件:
import { WebpackContext, ConfigurationContext } from '@malagu/cli-service';export default async (context: WebpackContext) => {const { configurations } = context;const config = ConfigurationContext.getFrontendConfiguration(configurations);if (config) {const { VueLoaderPlugin } = require('vue-loader');config.module.rule('vue').test(/\.vue$/).use('vue-loader').loader('vue-loader').end().end().rule('css').test(/\.css$/).use('vue-style-loader').loader('vue-style-loader').end().use('css-loader').loader('css-loader');config.plugin('vueLoader').use(VueLoaderPlugin);}};
插件代码存放到项目目录 src/webpack-hook.ts 或者 src/hooks/webpack.ts ,框架自动识别加载,也可以通过属性 webpackHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
configurationsWebpack 配置对象,与getWebpackConfig不同,getWebpackConfig获取的是组件属性中的malagu.webpackprogram命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息, 包含了
prod、mode、targets、dev、entry等信息
Deploy 插件
执行 malagu deploy 命令的时候,执行该插件。通过 Deploy 插件,我们可以自定义部署行为。比如使用 Deploy 插件实现项目部署到函数计算平台:
export default async (context: DeployContext) => {const { cfg } = context;const deployConfig = getMalaguConfig(cfg, BACKEND_TARGET)['faas-adapter'];const profileProvider = new ProfileProvider();profile = {...await profileProvider.provide(),...deployConfig.profile};const regions = deployConfig.regions || [profile.defaultRegion];for (region of regions) {await doDeploy(context, deployConfig);}};
插件代码存放到项目目录 src/deploy-hook.ts 或者 src/hooks/deploy.ts ,框架自动识别加载,也可以通过属性 deployHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
configurationsWebpack 配置对象,与getWebpackConfig不同,getWebpackConfig获取的是组件属性中的malagu.webpackprogram命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息, 包含了
prod、mode、targets、dev、entry等信息
Build 插件
执行 malagu build 命令的时候,执行该插件。通过 Build 插件,我们可以自定义构建行为。比如使用 Build 插件实现项目为部署到函数计算平台 custom 运行时,而生成 bootstrap 启动文件:
import { BuildContext, getHomePath } from '@malagu/cli-service';import { join } from 'path';import { writeFile } from 'fs-extra';import { FaaSAdapterUtils } from '@malagu/faas-adapter/lib/hooks';export default async (context: BuildContext) => {const { pkg, cfg } = context;const adapterConfig = FaaSAdapterUtils.getConfiguration<any>(cfg);if (adapterConfig.type === 'custom') {const destDir = join(getHomePath(pkg), 'bootstrap');const bootstrap = adapterConfig.function.bootstrap;delete adapterConfig.function.bootstrap;await writeFile(destDir, `#!/bin/bash\n${bootstrap}`, { mode: 0o755 });}};
插件代码存放到项目目录 src/build-hook.ts 或者 src/hooks/build.ts ,框架自动识别加载,也可以通过属性 buildHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
configurationsWebpack 配置对象,与getWebpackConfig不同,getWebpackConfig获取的是组件属性中的malagu.webpackprogram命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息, 包含了
prod、mode、targets、dev、entry等信息
Serve 插件
执行 malagu serve 命令的时候,执行该插件。通过 Serve 插件,我们可以自定义本地运行行为。比如使用 Serve 插件实现基于 Webpack Dev Server 的本地运行:
import { ServeContext } from '@malagu/cli-service';import * as express from 'express';export class Deferred<T> {resolve: (value?: T) => void;reject: (err?: any) => void; // tslint:disable-linepromise = new Promise<T>((resolve, reject) => {this.resolve = resolve;this.reject = reject;});}export default async (context: ServeContext) => {const { app, entryContextProvider } = context;app.use(express.json());app.use(express.raw());app.use(express.text());app.use(express.urlencoded({ extended: true }));let doDispatch: (req: any, res: any) => void;const compileDeferred = new Deferred<void>();context.compiler.hooks.done.tap('WebServe', () => {entryContextProvider().then(async (ctx: any) => {const { Dispatcher, Context, HttpContext, ContainerProvider, Application, container } = ctx;const c = await container;ContainerProvider.set(c);await c.get(Application).start();const dispatcher = c.get(Dispatcher);doDispatch = (req: any, res: any) => {const httpContext = new HttpContext(req, res);Context.run(() => dispatcher.dispatch(httpContext));};compileDeferred.resolve();});});app.all('*', async (req: any, res: any) => {await compileDeferred.promise;doDispatch(req, res);});};
插件代码存放到项目目录 src/serve-hook.ts 或者 src/hooks/serve.ts ,框架自动识别加载,也可以通过属性 serveHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
serverhttp 的 Server 对象app基础框架应用对象,例如 Express 的 Application 对象compilerWebpack 的编译对象entryContextProvider通过入口文件提供上下文的方法,通过该异步方法可以获取启动 Malagu 应用需要的上下文configurationsWebpack 配置对象,与getWebpackConfig不同,getWebpackConfig获取的是组件属性中的malagu.webpackprogram命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息,包含了
port、open、dev等信息
Config 插件
框架在应用配置计算表达式之前,执行该插件。通过 Config 插件,我们可以动态添加一些特殊的应用配置。比如使用 Config 插件为应用配置动态添加阿里云账号 ID:
import { ConfigContext } from '@malagu/cli-service';import { DefaultProfileProvider, FaaSAdapterUtils, FaaSAdapterConfiguration } from '@malagu/faas-adapter/lib/hooks';export default async (context: ConfigContext) => {const { config, cfg } = context;if (config.mode && config.mode.includes('remote')) {context.spinner?.stop();const adapterConfig = FaaSAdapterUtils.getConfiguration<FaaSAdapterConfiguration>(cfg);const profileProvider = new DefaultProfileProvider();const profile = await profileProvider.provide(adapterConfig);const faasAdapter = config.malagu['faas-adapter'];if (!faasAdapter.account?.id) {faasAdapter.account = profile.account;}if (!faasAdapter.region) {faasAdapter.region = profile.region;}}};
插件代码存放到项目目录 src/config-hook.ts 或者 src/hooks/config.ts ,框架自动识别加载,也可以通过属性 configHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
config应用配置对象program命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
Init 插件
执行 malagu init 命令的时候,执行该插件。比如:
import { InitContext } from '@malagu/cli';export default async (context: InitContext) => {...};
插件代码存放到项目目录 src/init-hook.ts 或者 src/hooks/init.ts ,框架自动识别加载,也可以通过属性 initHooks 自定义其他目录位置。
通过命令行上下文,我们可以取到一下相关信息:
program命令行对象,通过该对象可以获取命令相关信息pkg应用程序包,通过该对象可以获取应用程序包相关信息,例如应用版本、应用名称、应用包含的组件等等信息cfg应用配置信息,通过该对象可以获取应用配置信息,该应用的配置信息为所有组件属性聚合并计算了表达式以后的值。框架也提供了一些关于应用配置相关的工具方法:getConfig根据target获取前端或者后端配置getMalaguConfig根据target获取前端或者后端malagu配置getWebpackConfig根据target获取前端或者后端webpack配置
- 其他信息,包含了
name、tempate、outputDir等信息
