此页面介绍 src/install.js 文件,该文件仅在应用扩展安装时执行。并不是所有的扩展都需要一个安装脚本,这是一个可选项。
基本文件结构示例:
// 可以是异步的
export default function (api) {
// 下面描述了 "api" 对象的属性和方法
}api.engine
包含正在使用的 Quasar CLI 引擎名(字符串)。示例:@quasar/app-vite 或 @quasar/app-webpack。
api.hasVite
布尔值 - 是否在 @quasar/app-vite 上运行。
api.hasWebpack
布尔值 - 是否在 @quasar/app-webpack 上运行。
api.extId
包含此应用扩展的 ext-id(字符串)。
api.prompts
是一个包含在扩展安装时的提示答案的对象。有关提示的更多信息,请参阅 Prompts API。
api.resolve
在运行此应用扩展的应用程序内解析路径。消除了导入 path 并自行解析路径的需求。
// 解析到应用程序的根目录
api.resolve.app("src/my-file.js");
// 解析到应用程序的 root/src 目录
api.resolve.src("my-file.js");
// 解析到应用程序的 root/public 目录
// (@quasar/app-webpack v3.4+ 或 @quasar/app-vite v1+)
api.resolve.public("my-image.png");
// 解析到应用程序的 root/src-pwa 目录
api.resolve.pwa("some-file.js");
// 解析到应用程序的 root/src-ssr 目录
api.resolve.ssr("some-file.js");
// 解析到应用程序的 root/src-cordova 目录
api.resolve.cordova("config.xml");
// 解析到应用程序的 root/src-electron 目录
api.resolve.electron("some-file.js");
// 解析到应用程序的 root/src-bex 目录
api.resolve.bex("some-file.js");api.appDir
包含此扩展正在运行的宿主应用根目录的完整路径(字符串)。
api.hasTypescript @quasar/app-vite 1.6+ @quasar/app-webpack 3.11+
/**
* @return {Promise<boolean>} 宿主项目是否启用 TypeScript
*/
await api.hasTypescript();api.hasLint @quasar/app-vite 1.6+ @quasar/app-webpack 3.11+
/**
* @return {Promise<boolean>} 宿主项目是否启用 ESLint
*/
await api.hasLint();api.getStorePackageName @quasar/app-vite 1.6+ @quasar/app-webpack 3.11+
/**
* @return {Promise<string|undefined>} 'pinia' | 'vuex' | undefined
*/
await api.getStorePackageName();api.getNodePackagerName @quasar/app-vite 1.6+ @quasar/app-webpack 3.11+
/**
* @return {Promise<'npm' | 'yarn' | 'pnpm' | 'bun'>}
*/
await api.getNodePackagerName();api.compatibleWith
通过 semver 条件确保扩展与宿主应用程序中安装的程序包兼容。
如果不满足 semver 条件,则 Quasar CLI 会报错并停止执行。
semver 条件示例:'1.x || >=2.5.0 || 5.0.0 - 7.2.3'。
/**
* @param {string} packageName
* @param {string} semverCondition
*/
api.compatibleWith(packageName, "1.x");if (api.hasVite) {
api.compatibleWith("@quasar/app-vite", "^2.0.0");
} else {
api.compatbileWith("@quasar/app-webpack", "^4.0.0");
}api.hasPackage
检查宿主应用是否安装了某个包,并且可以通过 semver 条件设置版本。
semver 条件示例:'1.x || >=2.5.0 || 5.0.0 - 7.2.3'。
/**
* @param {string} packageName
* @param {string} (optional) semverCondition
* @return {boolean} package is installed and meets optional semver condition
*/
if (api.hasPackage("vuelidate")) {
// hey, this app has it (any version of it)
}
if (api.hasPackage("quasar", "^2.0.0")) {
// hey, this app has Quasar UI v2 installed
}api.hasExtension
检查另一个应用扩展是否通过 npm 安装并由 Quasar CLI 调用。
/**
* Check if another app extension is installed
*
* @param {string} extId
* @return {boolean} has the extension installed & invoked
*/
if (api.hasExtension(extId)) {
// hey, we have it
}api.getPackageVersion
获取宿主应用程序包的版本号。
/**
* @param {string} packageName
* @return {string|undefined} version of app's package
*/
console.log(api.getPackageVersion(packageName));
// output examples:
// 1.1.3
// undefined (when package not found)api.extendPackageJson
通过新属性扩展 package.json 文件的辅助方法。如果指定了现有属性,将覆盖它们。
/**
* @param {object|string} extPkg - Object to extend with or relative path to a JSON file
*/
api.extendPackageJson({
scripts: {
electron: "quasar dev -m electron",
},
});上面的示例向应用程序的 package.json 添加了一个 npm 脚本,因此您可以执行 yarn electron(或等效的 npm run electron)。
api.extendJsonFile
使用新属性(深度合并)扩展 JSON 文件。如果指定了现有属性,将覆盖它们。
/**
* @param {string} file (relative path to app root folder)
* @param {object} newData (Object to merge in)
*/
api.extendJsonFile("src/some.json", {
newProp: "some-value",
});api.render
从扩展的模板文件夹(您指定的任何文件夹)渲染(复制)到应用的根目录。保持与模板文件夹相同的文件夹结构。
如果应用中已经存在某些文件,则会询问用户是否应覆盖它们。
调用 render() 需要传递模板文件夹的相对路径。
/**
* Render a folder from extension templates into devland
* Needs a path (to a folder) relative to the path of the file where render() is called
*
* @param {string} templatePath (relative path to folder to render in app)
* @param {object} scope (optional; rendering scope variables)
*/
api.render("./path/to/a/template/folder");文件名的特殊情况
如果要渲染(复制)一个模板文件,其名称以点开头(例如 .env),则必须遵循特定的命名约定,因为发布插件到 npm 时会忽略点开头的文件:
# 包含点文件的模板必须使用下划线,替代其名称中的点:
some-folder/_env
# 当调用 api.render('./some-folder') 时,这将在项目文件夹中渲染为:
/.env如果要渲染一个文件,其名称实际上以下划线开头,则文件名必须以 __(两个下划线字符而不是一个)开头:
some-folder/__my.css
# 当调用 api.render('./template') 时,这将在项目文件夹中渲染为:
/_my.css使用 scope
您还可以通过插值使用 lodash/template 语法将一些决策代码注入到要渲染的文件中。
示例:
// (my-folder 与当前文件位于相同的文件夹中)
api.render("./my-folder", {
prompts: api.prompts,
});假设我们还使用了 Prompts API 文件。它询问用户是否要 “Feature X” 并将答案存储在名为 “featureX” 的变量中。
在渲染过程中,我们可以决定渲染的文件的内容。这样就不需要创建两个文件夹,也不需要根据某些决定来选择渲染哪个文件夹。
<% if (prompts.featureX) { %>
const message = 'This is content when "Feature X" exists'
<% } else { %>
const message = 'This is content when we don\'t have "Feature X"'
<% } %>可能性仅受您的想象力限制。
api.renderFile
与 api.render() 类似,区别在于该方法渲染单个文件。
/**
* Render a file from extension template into devland
* Needs a path (to a file) relative to the path of the file where renderFile() is called
*
* @param {string} relativeSourcePath (file path relative to the folder from which the install script is called)
* @param {string} relativeTargetPath (file path relative to the root of the app -- including filename!)
* @param {object} scope (optional; rendering scope variables)
*/
api.renderFile("./path/to/a/template/filename", "path/relative/to/app/root/filename", {
prompts: api.prompts,
});
api.renderFile("./my-file.json", "src/my-file.json");api.getPersistentConf
获取此扩展的内部持久配置。如果没有,则返回空对象。
/**
* @return {object} cfg
*/
api.getPersistentConf();api.setPersistentConf
设置此扩展的内部持久配置。如果已存在,则将其覆盖。
/**
* @param {object} cfg
*/
api.setPersistentConf({
// ....
});api.mergePersistentConf
深度合并到此扩展的内部持久配置中。如果扩展尚未设置任何配置,则这本质上等同于首次设置。
/**
* @param {object} cfg
*/
api.mergePersistentConf({
// ....
});api.onExitLog
在 App CLI 完成安装应用扩展并即将退出时添加一条日志。可以多次调用以注册多个退出日志。
/**
* @param {string} msg
*/
api.onExitLog("Thanks for installing my awesome extension");