Vue Cli plug-in development details
The original address
What is the CLI Plugin
To quote an official quote:
CLI plug-in is an NPM package that adds additional features to @vue/ CLI projects. It should always include a Service plug-in as its main export, and optionally include a Generator and a Prompt file.
Usually we need to pull out some of our own configuration/common components for use by each project, and other projects created using cli can be automatically imported by using vue Add oView.
Vue-cli plug-in directory structure
The directory structure of a typical CLI plug-in looks like this:
├── Prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt prompt package.jsonCopy the code
If you need to choose from the command line whether to create some sample components while the plug-in is installed, the directory can be changed to:
. ├ ─ ─ the README. Md ├ ─ ─ the generator | - - - the template │ └ ─ ─ index. The js # generator ├ ─ ─ prompts. Js # command prompt to install ├ ─ ─ index. The js # service Plug-in └ ─ ─ package. JsonCopy the code
Third, GeneratorAPI
A CLI plug-in published as an NPM package can contain a generator. Js or generator/index.js file. The generator inside the plug-in will be invoked in two scenarios:
-
During the initial creation of a project, if the CLI plug-in is installed as part of the project creation preset.
-
The plug-in is installed after the project is created when it is called independently via Vue Invoke.
(1) of the Generator
- to
package.json
Inject additional dependencies or fields, and add files to the project - use
ejs
Render the file under Generator /template.
Example:
module.exports = (api, options, rootOptions) = > {
// Modify the fields in 'package.json'
api.extendPackage({
scripts: {
test: "vue-cli-service test"}});// Copy and render all files in './template 'with ejS
api.render("./template");
if (options.foo) {
// Conditionally generate files}};Copy the code
(2) GeneratorAPI parameter description
A generator/index should export a function that takes three arguments:
-
An instance of GeneratorAPI:
-
Generator option for this plug-in. Prompts create a conversation parameter using Prompts. Js, or preset is loaded from a save in ~/.vuerc. For example, if you save ~/. Vuerc like this:
{ "presets": { "foo": { "plugins": { "@vue/cli-plugin-foo": { "option": "bar" } } } } } Copy the code
If the user creates a project using Preset Foo, the generator for @vue/cli-plugin-foo will receive {option: ‘bar’} as the second parameter.
For a third party plug-in, this option will be resolved in the command line arguments from the conversation or when the user executes Vue Invoke (see the conversation for third party plug-ins).
-
The entire preset (presets.foo) will be passed in as the third argument.
(3) Common APIS of Generator
See here for details of all apis, and here are some commonly used apis
onCreateComplete
-
The ginseng
{function}
The callback function
-
Usage: Callback function after plug-in file is written to disk, often used for custom plug-in Usage after installing dependencies. For example, import oView from “oView” in SRC /main.js; Vue.use(oView)
api.onCreateComplete(() = > {
let oview = `\nimport oView from 'oview'; \n\nVue.use(oView); `;
const fs = require("fs");
const mainPath = api.resolve("./src/main.js");
// Get the content
let contentMain = fs.readFileSync(mainPath, {
encoding: "utf-8"
});
if (contentMain.indexOf("oview") = = = -1) {
const lines = contentMain.split(/\r? \n/g).reverse();
/ / into the import
const lastImportIndex = lines.findIndex(line= > line.match(/^import/));
lines[lastImportIndex] += oview;
// Modify the application
contentMain = lines.reverse().join("\n");
fs.writeFileSync(mainPath, contentMain, {
encoding: "utf-8"}); }});Copy the code
extendPackage
-
The ginseng
{object | () => object}
-
Usage instructions: Add dependencies in package.json. Nested fields are deeply merged unless {merge: false} is passed. It also resolves dependency conflicts between plug-ins. Tool configuration fields can be extracted into separate files before files are written to disk.
render
-
The ginseng
{string | object | FileMiddleware}
– It could be one of the following three- Relative path to a folder: for example
./template
; {sourceTemplate: targetFile}
The object hash of the map;- Custom file middleware functions
- Relative path to a folder: for example
{object} [additionalData]
– Other data available to the template{object} [ejsOptions]
– ejs Specifies additional parameters
-
Usage: Use EJS to render files into the project structure
resolve
-
The ginseng
{string} _path
– Relative to the project root directory directory
-
The return value
{string}
– Absolute file path
-
Get the absolute path of a file/folder
hasPlugin
Determine if a plug-in already exists.
-
The ginseng
{string} id
– the plug-in id, can be omitted (@ vue / | vue – | @ the scope/vue) – cli – plugin – prefix{string} version
– Version range. This value is optional
-
The return value
{boolean}
cliVersion
Use the @vue/ CLI version of this plug-in
cliServiceVersion
Use the @vue/ CLI-service version of this plug-in.
4. Service plug-in
registerCommand
- Effect: Registers a file similar to the
vue-cli-service [name]
The command - The arguments:
- Command name (name),
- Optional parameter (OPTS)
{
description: string,
usage: string,
options: { [string]: string }
}
Copy the code
- Callback function (FN)
Vue-cli-service serve is an example
module.exports = (api, options) = > {
api.registerCommand('serve', {
description: 'start development server'.usage: 'vue-cli-service serve [options] [entry]'.options: {
'--open': `open browser on server start`.'--copy': `copy url to clipboard on server start`.'--mode': `specify env mode (default: development)`.'--host': `specify host (default: ${defaults.host}) `.'--port': `specify port (default: ${defaults.port}) `.'--https': `use https (default: ${defaults.https}) `.'--public': `specify the public network URL for the HMR client`.'--skip-plugins': `comma-separated list of plugin names to skip for this run`}},async function serve (args) {}Copy the code
chainWebpack
What is chainWebpack? Please see here
Webpack – chain website
- Action: Changes the WebPack configuration in a chained manner
- Input parameter: callback function
// An example: modify the default index.html file
api.chainWebpack(function(config) {
config.plugin("html").tap(args= > {
args[0].template = "/Users/username/proj/app/templates/index.html";
return args;
});
});
Copy the code
configureWebpack
ConfigureWebpack There are two ways to modify the Webpack configuration. Introduction to the solid Web Pack for Vue
- ConfigureWebpack for
Object
Type, yesMerge configuration into Webpack
api.configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
Copy the code
- ConfigureWebpack for
function
Type, yesModify the WebPack configuration directly
api.configureWebpack: config= > {
if (process.env.NODE_ENV === 'production') {
// Modify the configuration for the production environment...
} else {
// Modify the configuration for the development environment...}}Copy the code
resolveWebpackConfig
To get the modified WebPack configuration, we usually need to get the modified Webpack value after using api.configureWebPack or api.chainWebPack
api.chainWebpack(webpackConfig= > {
/ /...
});
// Get the modified Webpack value
const webpackConfig = api.resolveWebpackConfig();
Copy the code
resolveChainableWebpackConfig
Returns a chain chainWebpack configuration, resolveWebpackConfig is returned directly webpack configuration, but a chainWebpack resolveChainableWebpackConfig returns
version
Cli @vue/ CLI-service version in use.
getCwd
Current working directory
resolve
- Input parameter: directory relative to the root directory
- Return value: Absolute path
hasPlugin
- Effect: Checks whether a plug-in already exists for the project
- Input parameter: plug-in ID, which can be ignored
@vue/|vue-|@scope/vue
The prefix. - Reference: Boolean
Prompts
When you create a new project or add a new plug-in to an existing project, you need to be prompted to handle the user’s choices. All prompt logic is stored in the prompts. Js file.
Prompt in vue is the Inquirer used;
When the user initializes the plug-in through a call, vue Invoke is used during the invocation if the plug-in prompts. Js is contained in the root directory of the plug-in. The file should be exported to a series of issues that will be handled by Inquirer.
The prompt. Js export can be done in two ways:
- Export an array of questions
- Export a function that handles the problem
The result of the prompt. Js export will become the second argument to generator/index.jsoptions
.
Before introducing the above two, a brief introduction to the use of Inquirer
Inquirer.js
A question is an object:
{
type: "input|number|confirm|list|rawlist|expand|checkbox|password|editor".// The default value is input
name: String,// This is the id of the problem. You can use options.example to get the value of the problem
message:String | Function,// A problem to print. If defined as a function, the first argument will be the current inquirer session answer. The default is name (followed by a colon)
default:String | Number | Boolean | Array | Function,// If nothing is entered, the default value is used, or the function that returns the default value. If defined as a function, the first argument will be the current inquirer session answer,
choices:Array|Function,/ / (Array | Function) Choices Array or Function returns an Array of Choices. If defined as a function, the first argument will be the current inquirer session answer. Array values can be Simple numbers, Strings, or Objects containing the name (displayed in the list), value (stored in the name described above, and short (displayed after selection) attributesValidate: Function,// Verify that the input value meets the requirements
filter:Function,// Takes user input and returns the filtered values to be used internally in the program. The filtered values are returned to 'Answers', asking if the user is correct
when:Boolean|Function,// Accept the current user's answer hash and should return true or false depending on whether the question should be asked
pageSize:Number,/ / when using the list, rawList, expand, there may be a paging checkbox
prefix:String,// Change the default prefix message
suffix:String// Change the default postfix message
}
Copy the code
Export an array of questions
module.exports = [
{
type: "input".name: "locale".message: "The locale of project localization.".validate: input= >!!!!! input,default: "en"
}
// ...
];
Copy the code
Export the handling function
// The input parameter is package.json
module.exports = pkg= > {
const prompts = [
{
type: "input".name: "locale".message: "The locale of project localization.".validate: input= >!!!!! input,default: "en"}];// Dynamically add problems
if ("@vue/cli-plugin-eslint" in (pkg.devDependencies || {})) {
prompts.push({
type: "confirm".name: "useESLintPluginVueI18n".message: "Use ESLint plugin for Vue I18n ?"
});
}
return prompts;
};
Copy the code
Vue-cli-plugin-oview is an example
What does this instance do?
Install the mobile terminal chart library Oview using vuE-CLI plug-in, and add a broken line pattern example. The source address
- Initialize the NPM
npm init
# Then type vue-cli-plugin-oview
Copy the code
-
Creating index.js requires no command registration, so you just need to write the default export.
module.exports = (api, opts) = > {}; Copy the code
-
Write the generator to generate the template
- Creating a Generator directory
- Create a new index.js file
- Creating a template directory
The file directory is:
├ ─ the generator │ ├ ─ index. Js │ └ ─ template │ └ ─ SRC │ ├ ─ components │ │ └ ─ Line. The vue │ └ ─ mock │ └ ─ data. Js ├ ─ index, js ├ ─ package. Json ├ ─ prompts. Js └ ─ the README, mdCopy the code
The Chinese side of the template directory is the sample template, which the CLI will render using EJS.
- Add user validation We may need user validation to install instances,
// prompts.js
module.exports = [
{
name: "example".type: "confirm".message: "Do you want to add the sample component to the project Components directory?".default: false}];Copy the code
- Add dependencies, declared in main.js
// generator/index.js
module.exports = (api, options, rootOptions) = > {
// Add dependencies to package.json
api.extendPackage({
dependencies: {
oview: "^ 1.1.2." "}});// When the file is written to disk, read main.js and write import oView from "oView" in main.js; Vue.use(oView)
api.onCreateComplete(() = > {
let oview = `\nimport oView from 'oview'; \n\nVue.use(oView); `;
const fs = require("fs");
const mainPath = api.resolve("./src/main.js");
// Get the content
let contentMain = fs.readFileSync(mainPath, {
encoding: "utf-8"
});
if (contentMain.indexOf("oview") = = = -1) {
const lines = contentMain.split(/\r? \n/g).reverse();
/ / into the import
const lastImportIndex = lines.findIndex(line= > line.match(/^import/));
lines[lastImportIndex] += oview;
// Modify the application
contentMain = lines.reverse().join("\n");
fs.writeFileSync(mainPath, contentMain, {
encoding: "utf-8"}); }});// the parameters passed by prompt
if (options.example) {
// Render the template under template
api.render("./template", {... options }); }};Copy the code
- Create a new instance project to test the plug-in
vue create demo
# Change the following paths to your own
npm install --save-dev C:\Users\mrgao\Desktop\demo\vue-cli-plugin-oview
You can see this dependency in package.json
vue invoke vue-cli-plugin-oview
# Now you can see a command that prompts you whether to add a file or not, and if everything is OK, then you can find oView dependencies in package.json and oview in main.js
Copy the code
- Published to the NPM
1NPM config set registry HTTPS://registry.npmjs.org/
2To login to NPM, the user name, password, and email address must match NPM loginUsername: Your NPM usernamePassword:
Email: (thisIS your email address3NPM publish + ngx-xxx@0.01.Login HTTPS://www.npmjs.com/ you can see your own published projects
Copy the code
Give it a thumbs up! The original address
Example :oview plug-in
- vue-cli-plugin-oview
If you find this article useful, welcome to Star: mrgaogang.github. IO