
Vue CLI 插件开发完全指南从 Generator 到 Service Plugin 与 UI 集成【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-cliVue CLI 插件CLI Plugin是扩展 Vue CLI 项目能力的标准机制本文以 docs/dev-guide/plugin-dev.md 为骨架结合本仓库packages/vue/下各官方插件的真实实现系统讲解插件的目录结构、命名规范、Generator文件与依赖注入、Service Pluginwebpack 与命令扩展、Prompts交互式提问、本地测试、Vue UI 集成以及 npm 发布全流程。读完本文你将能够从零编写一个可被vue add安装、可接入vue ui图形界面的完整 Vue CLI 插件。插件是什么能力范围与目录结构一个 Vue CLI 插件本质上是一个 npm 包它可以在 Vue CLI 项目中追加额外能力典型包括修改项目的 webpack 配置——例如为某种文件扩展名新增 resolve 规则。官方插件vue/cli-plugin-typescript正是通过这种方式为.ts、.tsx扩展名添加解析规则新增vue-cli-service命令——例如vue/cli-plugin-unit-jest注册了test:unit命令让开发者可以运行单元测试扩展package.json——当插件为项目引入新依赖时可将依赖写入 dependencies 等字段创建新文件或修改旧文件——例如创建一个示例组件或在主文件中追加 import向用户提问以选择特定选项——例如询问用户是否要创建上述示例组件。需要提醒的是不要滥用插件机制。如果只是想引入某个依赖如 Lodash直接用npm install手动添加远比创建一个专用插件更简单。一个完整的 CLI 插件包含以下组成部分主出口Service Plugin必选、Generator可选、Prompts 文件可选、Vue UI 集成可选。作为 npm 包它必须有package.json也建议提供README.md帮助其他开发者在 npm 上发现它。典型的插件目录结构如下. ├── README.md ├── generator.js # generator可选 ├── index.js # service plugin主出口 ├── package.json ├── prompts.js # prompts 文件可选 └── ui.js # Vue UI 集成可选命名与可发现性CLI 插件必须遵循命名约定vue-cli-plugin-name或scope/vue-cli-plugin-name否则将无法被vue/cli-service发现也无法通过vue add name或vue invoke name安装。命名正确与否直接决定插件能否被 Vue UI 的插件搜索找到因此在发布前务必确认命名。为了提升搜索结果中的可发现性应在package.json的description字段中写入描述插件用途的关键词例如{ name: vue-cli-plugin-apollo, version: 0.7.7, description: vue-cli plugin to add Apollo and GraphQL }同时在homepage或repository字段中提供插件主页/仓库地址这样插件描述旁会显示一个「More info」按钮{ repository: { type: git, url: githttps://github.com/Akryum/vue-cli-plugin-apollo.git }, homepage: https://github.com/Akryum/vue-cli-plugin-apollo#readme }插件在 npm 搜索结果中呈现的效果含描述、作者与 More info 按钮可以参考本仓库 docs/public/plugin-search-item.png 所示。Generator注入依赖、渲染文件、改造现有代码Generator 是插件中负责往项目里写东西的部分通常用于为项目增加新依赖、创建新文件或编辑现有文件。它应放在插件根目录的generator.js或generator/index.js中并在两种场景下被调用项目初始创建时——插件作为项目创建 preset预设的一部分被安装项目创建后单独调用时——通过vue add或vue invoke安装插件。Generator 的三个参数Generator 导出的是一个函数它接收三个参数GeneratorAPI 实例——完整 API 参见 docs/dev-guide/generator-api.md该插件的 generator 选项——在项目创建的 prompt 阶段 解析得出或从~/.vuerc保存的 preset 中加载。例如~/.vuerc如下{ presets : { foo: { plugins: { vue/cli-plugin-foo: { option: bar } } } } }用户使用foopreset 创建项目时vue/cli-plugin-foo的 generator 将收到{ option: bar }作为第二个参数。对于第三方插件选项来自用户执行vue invoke时的 prompts 回答或命令行参数。整个 presetpresets.foo——作为第三个参数传入。创建新模板api.render 与 EJS调用api.render(./template)时generator 会使用 EJS 渲染./template目录相对 generator 文件解析中的所有文件。假设我们要实现 vue-cli-plugin-auto-routing 这类插件希望在插件调用时对项目做出如下改动创建layouts文件夹与一个默认布局文件创建pages文件夹包含about和home两个页面在src目录根部新增router.js。首先要将这套结构放到generator/template文件夹内结构示意见 docs/public/generator-template.png然后在generator/index.js中调用api.rendermodule.exports api { api.render(./template) }从本仓库源码看api.render位于 packages/vue/cli/lib/GeneratorAPI.js 的render方法约 L282-L324它支持三种入参——目录相对路径内部用globby遍历后逐一渲染、{ 源模板: 目标文件 }映射对象、以及自定义文件中间件函数渲染过程中会把options、rootOptions、plugins等数据注入模板因此模板中可以放心使用% options.xxx %这类 EJS 表达式。编辑已有模板YAML front-matter 的 extend / replace除了创建新文件你还可以继承并替换已有模板文件的局部内容甚至继承自其他包的文件这通过模板文件头部的 YAML front-matter 实现--- extend: vue/cli-service/generator/template/src/App.vue replace: !!js/regexp /script[^]*?\/script/ --- script export default { // Replace default script } /script也可以进行多次替换此时需要将替换内容包裹在%# REPLACE %与%# END_REPLACE %块中且replace字段改为正则数组替换顺序与块顺序一一对应--- extend: vue/cli-service/generator/template/src/App.vue replace: - !!js/regexp /Welcome to Your Vue\.js App/ - !!js/regexp /script[^]*?\/script/ --- %# REPLACE % Replace Welcome Message %# END_REPLACE % %# REPLACE % script export default { // Replace default script } /script %# END_REPLACE %这套机制的底层实现在 packages/vue/cli/lib/GeneratorAPI.js 的renderFile函数约 L478-L538它先用yaml-front-matter解析 front-matter通过resolve.sync定位extend指向的源文件再按replace正则单个或数组执行替换同时支持when字段做条件渲染条件为假时整段跳过避免无谓开销。文件名的边界情况点文件与下划线前缀npm 发布时会忽略点文件dotfiles因此渲染以点开头的模板文件需要特殊命名约定# 点文件模板需用下划线代替点 /generator/template/_env # 调用 api.render(./template) 后会在项目目录中渲染为 /generator/template/.env相应地如果文件名本身以下划线开头则需使用双下划线# 此类模板需用双下划线代替单下划线 /generator/template/__variables.scss # 渲染后在项目目录中为 /generator/template/_variables.scss该转换逻辑对应源码 packages/vue/cli/lib/GeneratorAPI.jsrender中 L291-L301 的文件名处理单下划线前缀映射为点前缀双下划线前缀去掉一个下划线。扩展 package.jsonextendPackage如需为项目添加依赖、新增 npm script 或以其他方式修改package.json使用api.extendPackage// generator/index.js module.exports api { api.extendPackage({ dependencies: { vue-router-layout: ^0.1.2 } }) }上面的示例添加了依赖vue-router-layout——插件调用期间该模块会被安装同时写入用户的package.json。同一个 API 也可以用来新增 npm 任务在scripts段指定任务名与要执行的命令即可// generator/index.js module.exports api { api.extendPackage({ scripts: { greet: vue-cli-service greet } }) }这里新增的greet任务对应的正是下文 Service Plugin 一节中自定义的vue-cli-service命令。从源码 packages/vue/cli/lib/GeneratorAPI.js 的extendPackageL225-L269可以看到它并非简单覆盖dependencies/devDependencies走专门的版本冲突合并逻辑mergeDeps数组去重合并嵌套对象深度合并deepmerge并支持prune、merge、forceOverwrite等选项——这保证了多个插件同时注入依赖时不会互相覆盖版本。修改主文件entryFile、injectImports 与 afterInvoke通过 generator 方法可以修改项目文件最常见的是对main.js/main.ts的改动新增 import、追加Vue.use()调用等。接续上面的场景我们已经通过模板创建了router.js现在想把它导入主文件。这里用到两个 APIapi.entryFile返回项目主文件main.js或main.ts自动识别 TypeScriptapi.injectImports用于向该文件追加 import// generator/index.js api.injectImports(api.entryFile, import router from ./router)导入之后需要把 router 注入到主文件里的 Vue 实例。由于此时文件尚未落盘应使用afterInvoke钩子——它在文件写入磁盘后触发。首先用 Nodefs模块读取主文件内容并按行切分// generator/index.js module.exports.hooks (api) { api.afterInvoke(() { const fs require(fs) const contentMain fs.readFileSync(api.resolve(api.entryFile), { encoding: utf-8 }) const lines contentMain.split(/\r?\n/g) }) }接着找到包含render的那一行通常是 Vue 实例的一部分在其后追加router// generator/index.js module.exports.hooks (api) { api.afterInvoke(() { const fs require(fs) const contentMain fs.readFileSync(api.resolve(api.entryFile), { encoding: utf-8 }) const lines contentMain.split(/\r?\n/g) const renderIndex lines.findIndex(line line.match(/render/)) lines[renderIndex] \n router, }) }最后把内容写回主文件注意使用os.EOL处理跨平台换行// generator/index.js module.exports.hooks (api) { api.afterInvoke(() { const { EOL } require(os) const fs require(fs) const contentMain fs.readFileSync(api.resolve(api.entryFile), { encoding: utf-8 }) const lines contentMain.split(/\r?\n/g) const renderIndex lines.findIndex(line line.match(/render/)) lines[renderIndex] ${EOL} router, fs.writeFileSync(api.resolve(api.entryFile), lines.join(EOL), { encoding: utf-8 }) }) }值得一提的是官方插件 packages/vue/cli-plugin-router/generator/index.js 就是这些 API 的典型组合应用api.injectImports(api.entryFile, import router from ./router)注入 importVue 2 项目用api.injectRootOptions(api.entryFile, router)注入根选项、Vue 3 项目用api.transformScript(api.entryFile, require(./injectUseRouter))执行 codemod随后api.extendPackage按 Vue 版本注入vue-router依赖api.render渲染对应版本的模板并用api.hasPlugin(typescript)判断是否触发额外的 TS 文件转换。afterInvoke、injectRootOptions、transformScript等方法的实现同样在 packages/vue/cli/lib/GeneratorAPI.js 中可查分别见 L345-L347、L428-L436、L392-L410。Service Plugin服务插件Service plugin 用于修改 webpack 配置、创建新的vue-cli-service命令或修改现有命令如serve、build。它位于插件根目录的index.js并且在 Service 实例创建时被自动加载——也就是说每次在项目内执行vue-cli-service命令时都会加载。Service plugin 导出的函数接收两个参数PluginAPI 实例——完整 API 参见 docs/dev-guide/plugin-api.md项目本地选项对象——来自vue.config.js或package.json中的vue字段。Service plugin 文件的最小代码只需要module.exports () {}从加载流程看packages/vue/cli-service/lib/Service.js 的resolvePluginsL169-L235会从项目devDependencies/dependencies中筛选出所有符合isPlugin判断的依赖并逐个requireinitL58-L99在加载.env与用户配置后会以apply(new PluginAPI(id, this), this.projectOptions)的形式调用每个插件见 L80-L83。此外它还支持在package.json的vuePlugins.service字段中声明本地插件文件。修改 webpack 配置API 允许 service plugin 针对不同环境扩展/修改内部 webpack 配置。例如用 webpack-chain 将vue-auto-routingwebpack 插件及其参数注入配置const VueAutoRoutingPlugin require(vue-auto-routing/lib/webpack-plugin) module.exports (api, options) { api.chainWebpack(webpackConfig { webpackConfig .plugin(vue-auto-routing) .use(VueAutoRoutingPlugin, [ { pages: src/pages, nested: true } ]) }) }也可以使用configureWebpack方法修改 webpack 配置或返回一个对象由webpack-merge合并进去。结合源码看这两种方式的差异chainWebpack会把回调推入service.webpackChainFns在 packages/vue/cli-service/lib/PluginAPI.jsL97-L99与 Service 的resolveChainableWebpackConfigpackages/vue/cli-service/lib/Service.js L265-L270中体现为先构造链式配置再调用所有 chain 回调最终由resolveWebpackConfigL272-L334统一转为 raw config而configureWebpack的回调被推入webpackRawConfigFns在resolveWebpackConfig中依次执行函数可原地修改配置或返回对象进行 merge。官方插件 packages/vue/cli-plugin-babel/index.js 是chainWebpack的深度范例它在jsrule 上设置.test(/\.m?jsx?$/)与排除逻辑按transpileDependencies配置决定是否转译 node_modules追加babel-loader选项并使用api.genCacheConfig(babel-loader, {...}, [babel.config.js, .browserslistrc])生成缓存目录与缓存标识——genCacheConfig的实现见 packages/vue/cli-service/lib/PluginAPI.js L151-L214它会综合 cli-service 版本、NODE_ENV、chainWebpack/configureWebpack函数源码、lock 文件与指定配置文件内容计算 hash保证配置变化时缓存自动失效。注册新的 cli-service 命令使用api.registerCommand可以注册标准命令serve、build之外的新命令。下面创建一条向开发者控制台输出问候语的简单命令api.registerCommand( greet, { description: Writes a greeting to the console, usage: vue-cli-service greet }, () { console.log( Hello) } )这里提供了命令名greet、包含description与usage的选项对象以及执行vue-cli-service greet时运行的函数。运行结果如下$ vue-cli-service greet Hello!registerCommand还支持为命令声明可用选项列表。为命令添加--name选项并让函数在提供该参数时输出对应名字api.registerCommand( greet, { description: Writes a greeting to the console, usage: vue-cli-service greet [options], options: { --name: specifies a name for greeting } }, args { if (args.name) { console.log( Hello, ${args.name}!); } else { console.log( Hello!); } } );带参运行的效果$ vue-cli-service greet --name John Doe Hello, John Doe!从源码看packages/vue/cli-service/lib/PluginAPI.js 的registerCommandL82-L88会将命令注册进this.service.commands[name] { fn, opts }命令执行时由 packages/vue/cli-service/lib/Service.js 的run方法L237-L263解析 mode、初始化后取出fn(args, rawArgv)调用。官方插件 packages/vue/cli-plugin-eslint/index.js 中注册的lint命令就是一个带大量选项--no-fix、--max-errors、--output-file等与details说明的完整示例。修改现有的 cli-service 命令如需修改已有命令可以从api.service.commands中取出它再附加改动。下面在应用启动时打印运行端口const { serve } api.service.commands const serveFn serve.fn serve.fn (...args) { return serveFn(...args).then(res { if (res res.url) { console.log(Project is running now at ${res.url}) } }) }示例中先取出已有serve命令再包装其fn即注册命令时传入的执行函数改造后serve成功运行完毕就会输出这条控制台消息。为命令指定默认模式defaultModes如果插件注册的命令需要在特定默认模式下运行插件必须通过module.exports.defaultModes以{ [commandName]: mode }的形式暴露它module.exports api { api.registerCommand(build, () { // ... }) } module.exports.defaultModes { build: production }这是因为命令期望的 mode 必须在加载环境变量之前被知晓而环境变量的加载又必须先于用户选项的加载与插件的应用。该机制的实现可见 packages/vue/cli-service/lib/Service.js 构造函数L41-L43构造 Service 时即聚合所有插件的defaultModes生成this.modes随后run方法L241在init之前据此解析 mode。文件顶部注释L5-L8也明确说明不能等到应用插件时才读取defaultModes。Prompts交互式提问Prompts 用于在创建新项目或向已有项目添加插件时处理用户选择所有逻辑存放在prompts.js文件中底层由 inquirer 驱动。当用户通过vue invoke初始化插件时如果插件根目录存在prompts.js它就会被用于本次调用该文件应导出一个由 inquirer Question 组成的数组既可以直接导出数组也可以导出返回数组的函数。直接导出问题数组// prompts.js module.exports [ { type: input, name: locale, message: The locale of project localization., validate: input !!input, default: en }, // ... ]导出返回数组的函数可以拿到项目package.json做动态判断// prompts.js // 将项目的 package.json 作为参数传入函数 module.exports pkg { const prompts [ { type: input, name: locale, message: The locale of project localization., validate: input !!input, default: en } ] // 动态追加 prompt if (vue/cli-plugin-eslint in (pkg.devDependencies || {})) { prompts.push({ type: confirm, name: useESLintPluginVueI18n, message: Use ESLint plugin for Vue I18n ? }) } return prompts }解析后的回答对象会作为选项传给插件的 generator。另外用户也可以跳过 prompts直接通过命令行传参初始化插件vue invoke my-plugin --mode awesomeinquirer 支持多种 prompt 类型CLI 中最常用的是checkbox和confirm。给插件加一个confirmprompt并让 generator 依据回答决定是否渲染模板// prompts.js module.exports [ { name: addExampleRoutes, type: confirm, message: Add example routes?, default: false } ]调用插件时用户会被询问是否添加示例路由默认答案为No实际提问效果见 docs/public/prompts-example.png。generator 中通过 prompt 的name读取用户选择if (options.addExampleRoutes) { api.render(./template, { ...options }) }这样只有用户同意创建示例路由时模板才会被渲染。官方插件 packages/vue/cli-plugin-router/prompts.js 展示了真实写法它通过confirm类型的historyModeprompt 询问是否使用 history 模式并在description中补充说明生产环境需要服务器正确配置 index fallback。安装插件到本地项目进行测试开发插件过程中需要在实际项目里验证效果。可以复用现有项目也可以新建一个测试项目vue create test-app然后在项目根目录执行以下命令添加插件npm install --save-dev file:/full/path/to/your/plugin vue invoke your-plugin-name注意每次修改插件后都需要重复这两步。另一种方式是借助 Vue UI 图形界面。运行vue ui浏览器会在localhost:8000打开 UI。进入Vue Project Manager标签页见 docs/public/ui-project-manager.png找到你的测试项目见 docs/public/ui-select-plugin.png。点击项目名进入Plugins 选项卡拼图图标点击右上角的Add new plugin按钮在新视图的 npm 插件列表底部有Browse local plugin按钮见 docs/public/ui-browse-local-plugin.png点击后即可搜索并添加本地插件。添加完成后插件会出现在列表中点击Refresh 图标即可应用对插件所做的全部修改见 docs/public/ui-plugin-refresh.png。Vue UI 集成Vue CLI 自带图形化工具可以以可视化方式脚手架化与管理项目。插件可以接入该界面从而获得额外能力直接在 UI 中运行 npm 任务包括插件专属任务为插件展示自定义配置界面例如 vue-cli-plugin-apollo 提供了 Apollo server 配置屏见 docs/public/ui-configuration.png创建项目时以可视化方式展示 prompts为支持多语言添加本地化让插件在 Vue UI 搜索中可被发现。所有与 Vue UI 相关的逻辑应放在插件根目录的ui.js或ui/index.js中导出一个接收 api 对象的函数module.exports api { // Use the API here... }增强augmentUI 中的任务插件不仅可以通过 Generator 添加 npm 任务还能为它们在 Vue UI 中创建展示视图方便直接在 UI 中运行并查看输出。UI 的任务由项目package.json的scripts字段生成可通过api.describeTask为任务补充信息与钩子。为之前创建的greet任务提供附加说明module.exports api { api.describeTask({ match: /greet/, description: Prints a greeting in the console, link: https://cli.vuejs.org/dev-guide/plugin-dev.html#core-concepts }) }之后在 Vue UI 的Tasks区块就能看到该任务包括任务名、描述、指向 URL 的链接图标以及任务输出面板见 docs/public/ui-greet-task.png。官方插件 packages/vue/cli-plugin-unit-jest/ui.js 展示了更完整的用法describeTask中match: /vue-cli-service test:unit/匹配任务prompts声明watch、notify、update等运行参数支持when条件onBeforeRun钩子把用户选择转为命令行参数如--watch、--updateSnapshot。展示配置界面describeConfig项目可能拥有不同功能/库的自定义配置文件插件可以在 Vue UI 中展示、修改并保存它保存会实际改写项目中的对应配置文件。默认情况下 Vue CLI 项目有代表vue.config.js设置的主配置屏若项目包含 ESLint 还会显示 ESLint 配置屏见 docs/public/ui-configuration-default.png。要为插件构建自定义配置界面首先确保插件调用后项目根目录存在承载配置的文件——这意味着需要在模板渲染阶段把它加入template文件夹。默认情况下配置 UI 可读写以下文件类型json、yaml、js、package。将新文件命名为myConfig.js并放在template根目录. └── generator ├── index.js └── template ├── myConfig.js └── src ├── layouts ├── pages └── router.js给该文件填入实际配置// myConfig.js module.exports { color: black }插件被调用后myConfig.js会被渲染到项目根目录。接下来在ui.js中用api.describeConfig注册新配置屏先传入基本信息// ui.js api.describeConfig({ // 配置的唯一 ID id: org.ktsn.vue-auto-routing.config, // 显示名称 name: Greeting configuration, // 名称下方显示 description: This config defines the color of the greeting printed, // More info 链接 link: https://github.com/ktsn/vue-cli-plugin-auto-routing#readme })id 必须正确命名空间化因为它在所有插件间必须唯一推荐使用反向域名表示法。配置图标可以为配置选择图标既可以是 Material icon 的 Public static files 一节// ui.js api.describeConfig({ /* ... */ // 配置图标 icon: color_lens })未指定图标时若插件有 logo 则显示插件 logo见下文 Logo。声明配置文件需要把配置文件提供给 UI使其能读取内容并保存改动——为配置文件命名、选择格式并提供路径api.describeConfig({ // other config properties files: { myConfig: { js: [myConfig.js] } } })可以声明多个文件例如存在myConfig.json时用json: [myConfig.json]提供。列表中顺序重要第一个文件名将用于在配置文件不存在时创建它。展示配置 promptsonRead要在配置屏上为color属性展示输入框需要onRead钩子返回要展示的 prompts 列表api.describeConfig({ // other config properties onRead: ({ data }) ({ prompts: [ { name: color, type: input, message: Define the color for greeting message, value: white } ] }) })以上配置生成的界面效果见 docs/public/ui-config-start.png。接着把硬编码的white替换为配置文件中的属性值——onRead钩子的data对象包含每个配置文件内容的 JSON 结果。myConfig.js内容为// myConfig.js module.exports { color: black }则data对象为{ // 文件 myConfig: { // 文件数据 color: black } }因此需要的属性是data.myConfig.color修改onRead// ui.js onRead: ({ data }) ({ prompts: [ { name: color, type: input, message: Define the color for greeting message, value: data.myConfig data.myConfig.color } ] }),注意屏幕加载时配置文件可能不存在此时myConfig可能为 undefined。也可以为文件缺失的情况提供默认值// ui.js onRead: ({ data }) ({ prompts: [ { name: color, type: input, message: Define the color for greeting message, value: data.myConfig data.myConfig.color, default: black, } ] }),保存配置改动onWriteonWrite钩子用于把配置屏上的改动写回文件。它可接收很多参数这里只用到prompts与api前者是当前 prompts 的运行时对象从中取出 prompt id后者提供async getAnswer()方法按 id 取回答// ui.js async onWrite({ api, prompts }) { const result {} for (const prompt of prompts) { result[${prompt.id}] await api.getAnswer(prompt.id) } api.setData(myConfig, result) }在配置屏把颜色从black改为red并点击Save the changes后项目中的myConfig.js会同步更新// myConfig.js module.exports { color: red }在 UI 中展示 prompts通过 UI 安装插件时prompts 会在插件调用步骤可视化展示。可以给 inquirer 对象 扩展仅供 UI 使用的附加属性均为可选// prompts.js module.exports [ { // 基本 prompt 属性 name: addExampleRoutes, type: confirm, message: Add example routes?, default: false, // UI 相关 prompt 属性 group: Strongly recommended, description: Adds example pages, layouts and correct router config, link: https://github.com/ktsn/vue-cli-plugin-auto-routing/#vue-cli-plugin-auto-routing } ]效果是在插件调用时呈现分组、描述与链接的完整界面见 docs/public/ui-prompts.png。Logo 徽标可以在发布到 npm 的包根目录放置logo.png它会显示在以下位置搜索待安装插件时已安装插件列表中配置列表默认显示增强任务的列表默认显示。效果见 docs/public/plugins.png。Logo 应为方形、不透明的图片理想尺寸 84x84。发布插件到 npm发布前需在 npmjs.com 注册账号并全局安装npm。若是首次发布 npm 模块先登录npm login输入用户名和密码后凭据会被保存后续发布无需重复输入。发布前务必确认命名符合vue-cli-plugin-name约定参见上文可发现性。然后在插件根目录执行npm publish发布成功后就可以在 Vue CLI 创建的项目中用vue add plugin-name安装你的插件了。总结与进一步阅读一个完整的 Vue CLI 插件由四部分构成Generator负责注入依赖、渲染模板、改造主文件Service Plugin负责扩展 webpack 配置与vue-cli-service命令Prompts负责与用户交互并驱动 Generator 选项ui.js负责接入 Vue UI 图形界面。命名遵循vue-cli-plugin-name约定是插件可安装、可被发现的前提。本文涉及的 API 细节与底层机制可继续深入以下仓库文件Generator API 参考docs/dev-guide/generator-api.md实现见 packages/vue/cli/lib/GeneratorAPI.jsService Plugin API 参考docs/dev-guide/plugin-api.md实现见 packages/vue/cli-service/lib/PluginAPI.jsService 加载与命令执行机制packages/vue/cli-service/lib/Service.jsUI 集成 APIdocs/dev-guide/ui-api.md官方插件范例router 插件的 Generator 与 Promptspackages/vue/cli-plugin-router/generator/index.js、packages/vue/cli-plugin-router/prompts.js、babel 插件的 webpack 链式配置packages/vue/cli-plugin-babel/index.js、eslint 插件的命令注册packages/vue/cli-plugin-eslint/index.js、unit-jest 插件的 UI 任务增强packages/vue/cli-plugin-unit-jest/ui.js。【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考