等效的入门套件

本指南适用于您想要创建本质上是“入门工具包”的情况,该工具包可在官方入门工具包的顶部添加内容(/quasar.config.js配置、文件夹、文件、CLI挂钩)。 这使您可以使多个项目共享一个公共的结构/逻辑(并且只有一个软件包来管理它们,而不必单独更改所有项目以匹配您的通用模式),还可以与社区共享所有这些。

TIP

为了创建应用扩展项目文件夹,请首先阅读开发指南>简介.

完整例子

要查看我们将构建的示例,请转到MyStarterKit完整示例, 它是此应用程序扩展的一个Github存储库。

我们将创建一个示例应用扩展,它执行以下操作:

  • 它提示用户要此应用扩展安装哪些功能
  • 根据他给出的答案将文件渲染(复制)到宿主文件夹中
  • 它扩展了/quasar.config.js
  • 扩展了Webpack配置
  • 它使用应用扩展钩子(onPublish)
  • 卸载应用扩展程序后,它将删除添加的文件
  • 它使用提示定义应用扩展的功能

结构

出于本示例的目的,我们将创建以下文件夹结构:

.
├── README.md
├── package.json
└── src
    ├── boot
    │   └── my-starter-kit-boot.js
    ├── templates
    │   ├── common-files
    │   │   ├── README.md
    │   │   └── some-folder
    │   │       └── tasks.md
    │   ├── serviceA
    │   │   └── src
    │   │       └── services
    │   │           └── serviceA.js
    │   └── serviceB
    │       └── src
    │           └── services
    │               └── serviceB.js
    ├── index.js
    ├── install.js
    ├── prompts.js
    └── uninstall.js

安装脚本

下面的安装脚本仅将文件渲染到宿主应用中。 注意上面的src/templates文件夹,我们决定保留这些模板。

// src/install.js

module.exports = function (api) {
  // (可选!)
  // Quasar 兼容性检查; 您可能需要硬性依赖性,
  // 例如最低版本的“quasar”软件包
  // 或最低版本的Quasar App CLI
  api.compatibleWith('quasar', '^2.0.0')

  if (api.hasVite === true) {
    api.compatibleWith('@quasar/app-vite', '^1.0.0-beta.0')
  }
  else { // api.hasWebpack === true
    api.compatibleWith('@quasar/app-webpack', '^3.0.0')
  }

  // 我们将一些文件渲染到宿主项目中

  if (api.prompts.serviceA) {
    api.render('./templates/serviceA')
  }

  if (api.prompts.serviceB) {
    // 我们向模板
    // 提供插值变量
    api.render('./templates/serviceB', {
      productName: api.prompts.productName
    })
  }

  // 我们总是渲染以下模板:
  api.render('./templates/common-files')
}

请注意,我们使用提示来决定要渲染到宿主项目中的内容。 此外,如果用户选择了“服务B”,那么我们还将拥有一个“productName”,我们可以在渲染服务B的文件时使用它。

索引脚本

我们在索引脚本中做一些事情,例如扩展/quasar.config.js,钩入许多Index API钩子(在本例中为onPublish)的其中一个,并链到Webpack配置:

// src/index.js

module.exports = function (api) {
  // (可选!)
  // Quasar 兼容性检查; 您可能需要硬性依赖性,
  // 例如最低版本的“quasar”软件包
  // 或最低版本的Quasar App CLI
  api.compatibleWith('quasar', '^2.0.0')
  
  if (api.hasVite === true) {
    api.compatibleWith('@quasar/app-vite', '^1.0.0-beta.0')
  }
  else { // api.hasWebpack === true
    api.compatibleWith('@quasar/app-webpack', '^3.0.0')
  }
  
  // 在这里,我们扩展了/quasar.config.js;
  // (extendQuasarConf() 将在本教程的后面定义,继续阅读)
  api.extendQuasarConf(extendQuasarConf)

  // 在此,仅当用户回答他想要发布服务时,
  // 我们才注册onPublish挂钩
  if (api.prompts.publishService) {
    // onPublish() 将在本教程的后面定义,继续阅读
    api.onPublish(onPublish)
  }

  if (api.hasVite === true) {
    api.extendViteConf(extendVite)
  }
  else { // api.hasWebpack === true
    // 我们在Webpack配置中添加/更改/删除某些内容
    // (chainWebpack() 将在本教程的后面定义,继续阅读)
    api.chainWebpack(chainWebpack)
  }

  // 还有更多的钩子可以使用...
}

这是一个extendQuasarConf定义的例子:

function extendQuasarConf (conf, api) {
  conf.extras.push('ionicons-v4')
  conf.framework.iconSet = 'ionicons-v4'

  //
  // 我们注册一个启动文件。 用户不需要篡改它,
  // 因此我们将其保留在应用扩展代码中:
  //

  // 确保已注册my-ext启动文件
  conf.boot.push('~quasar-app-extension-my-starter-kit/src/boot/my-starter-kit-boot.js')

  // @quasar/app-vite不需要这个
  if (api.hasVite !== true) {
    // 确保启动文件被编译
    conf.build.transpileDependencies.push(/quasar-app-extension-my-starter-kit[\\/]src/)
  }
}

onPublish函数:

function onPublish (api, { arg, distDir }) {
  // 当调用“quasar build --publish”时,将调用此钩子

  // 您的发布逻辑在这里...
  console.log('We should publish now. But maybe later? :)')

  // 我们是否要发布Cordova应用程序?
  if (api.ctx.modeName === 'cordova') {
    // 做一点事
  }
}

extendVite函数:

function extendVite (viteConf, { isClient, isServer }, api) {
  // viteConf是一个由Quasar CLI生成的Vite配置对象。
}

chainWebpack函数:

function chainWebpack (cfg, { isClient, isServer }, api) {
  // cfg是Webpack链对象;
  // 有关如何使用它的文档:webpack-chain文档 (https://github.com/neutrinojs/webpack-chain)
}

卸载脚本

卸载应用扩展后,我们需要进行一些清理。 但是要当心您从应用程序空间中删除的内容! 可能仍需要一些文件。 如果您决定使用卸载脚本,请格外小心。

// 我们将其yarn添加到我们的应用扩展中,
// 因此我们可以导入以下内容:
const rimraf = require('rimraf')

module.exports = function (api) {
  // 删除文件夹时要小心! 
  // 您不想删除该项目仍需要的文件,
  // 或者不属于此应用扩展的文件。

  // 在这里,我们还可以完全删除/src/services文件夹,
  // 但是,如果用户将其他文件添加到该文件夹中怎么办?

  if (api.prompts.serviceA) {
    // 我们在安装时添加了它,因此我们将其删除
    rimraf.sync(api.resolve.src('services/serviceA.js'))
  }

  if (api.prompts.serviceB) {
    // 我们在安装时添加了它,因此我们将其删除
    rimraf.sync(api.resolve.src('services/serviceB.js'))
  }

  // 我们在安装时添加了它,因此我们将其删除
  rimraf.sync(api.resolve.app('some-folder'))
  // 警告...我们已经添加了此文件夹,但是如果
  // 开发人员将更多文件添加到此文件夹中???
}

注意,我们正在请求rimrafnpm软件包。 这意味着我们将yarn/npm添加到我们的应用扩展项目中。