Command line template creation page tutorial
One, foreword
In everyday business development, we often develop similar pages in different projects, or even in the same project.
The basic operation of that guy is to go through the old project and copy the code to change (waste time).
Today we are going to look at a project that allows you to create specific page code in your project with a single command.
Second, preparation
We need to push the project to NPM to realize this function, so those who do not have an NPM account should create an NPM account in advance. And create a Git repository for the project.
Create a Git repository
Execute NPM init in the repository to give the project an initialized package.json.
And add the address of the repository to the package.json file
{..."repository": {
"url": "https://github.com/xxx/xxx.git"}}Copy the code
Create a command line
Start by installing a dependency for your project
yarn
or
npm
Copy the code
Add another.gitignore file
node_modules
* lock.json;
Copy the code
Define the command header
Start by customizing a command line. Such as:
I want to see the version number of the project through -v.
Cblock add Page pageName to create a file.
That requires defining the name of the cblock.
Add some code to package.json:
{
"bin": {
"cblock": "lib/index.js"}}Copy the code
If the command line header is cblock, it will go to the lib/index.js file by default.
2. Create a file entry
From the file path above, we can see that we need to create the lib/index.js file in the root directory.
#! /usr/bin/env node
require(".. /bin/index");
Copy the code
Many of you must be curious #! /usr/bin/env node
Used to indicate that the script file will be executed using Node.
/usr/bin/env is used to tell the user to look for node in the path directory.
#! The /usr/bin/env node allows the system to dynamically look up nodes to solve the problem of different user Settings on different machines.
The command must be placed in the first line. Otherwise, it will not take effect.
Through the require (“.. /bin/index”); We also need to create a bin/index.js file in the following directory.
3, implementation,-v
Viewing the Version Number
Here we need to install a Commander library. Yarn add commander.
After the installation we will implement bin/index.js code
#! /usr/bin/env node
const { program } = require("commander");
/** * command line parsing */
const commanderAction = (command, type, name) = > {
console.log(command, type, name);
};
program
.version("0.0.1"."-v --version -V")
.arguments("<command> <type> <name>")
.action(commanderAction)
.parse(process.argv);
// Code parsing is below
Copy the code
Okay, so once we’ve written the simplest code we’re going to send out an NPM package
Note here, NPM can not use Taobao source, to switch to NPM source.
NPM publish --access=public // Publish private packages NPM publish --access=publicCopy the code
After executing the command, open the NPM official website and enter our package name to see if the version is released successfully. The following figure confirms that we have successfully released the NPM package.
4, test,-v
The command
Open the terminal and type:
# global install
yarn global add @dlijs/createpage
cblock -v
cblock add page Foo
Copy the code
We can obtain the following result:
5. Code parsing
First we go to the CommanderJS website
program
为commander
Global object of.version
For the set version, the default option is-V
和--version
After the version is set, the current version number is displayed.arguments
Used to specify command line arguments.action
The method of executing a command. After entering the command line, press Enter to execute the commandaction
And can bring out the command-line arguments you typed..parse(process.argv)
Processing parameters (not correctly understood)
4. Establish a local test environment
Then we need to implement the business logic, we will need to constantly test, constantly modify, then we can not send a NPM version every test, that is too expensive. So we need to set up a local test environment.
At the root of our createpage, type the command line YARN link.
The functionality is to do local project testing.
First let’s create a test project for Alita or UMI.
After installing the dependencies, type in the following order in the root directory of demo:
# Change the project name to your own project
yarn add @dlijs/createpage
yarn link @dlijs/createpage
Copy the code
After typing, you should see the following screenshot:
At this time. We go to the bin/index.js folder to change the version number.
program.version("Hundreds"."-v --version -V");
Copy the code
After saving, we’ll type under demo:
npx cblock -v
Copy the code
The test demo has succeeded in the local project on link. Now we can verify this as soon as we modify the CBlock project.
5. Verify the correctness of command lines
Now we are ready to write the core business of the project.
Before writing the project, we can install a colors-CLI library to print color-coded words on the console.
Then create the/SRC/Components folder under the root of your project, and create two simple components in that folder.
Before we develop, let’s think about the logic of this piece of content.
The first step is to determine whether the command line conforms to the specification. If it does not, there is no need to continue. End with an error message.
Next to determine whether the user input pageName has a corresponding component name. If yes, copy the file again. If not, we will be prompted that the component does not exist under our project. Please modify pageName and re-enter the command.
First we change the commanderAction method.
Custom methods in the code are added below
/** * command line parsing */
const commanderAction = (command, type, name) = > {
// Determine whether the command line conforms to the specification
if (verifyCommand(command, type) === "page") {
// Check whether the pageName entered by the user is in the project folder
if (checkNameExist(getComponents(), name)) {
console.log("File migration is ready.");
} else {
// If there is no such thing, just go to the endexitNoExistName(); }}else {
// The command line does not conform to the specificationexitCommander(); }};Copy the code
Write two methods in the /bin/index.js file:
const color = require("colors-cli");
/ / end commander
const exitCommander = () = > {
console.error(color.red("The command number entered is incorrect. For the time being, only:"));
console.log(color.red("cblock add page <name>"));
console.log(color.red("Please re-enter ~"));
process.exit();
};
// Failed to find blocks and ended the project
const exitNoExistName = () = > {
console.log(color.red("Could not find the block, please confirm the block name!"));
console.log(color.red("Please re-enter ~"));
process.exit();
};
Copy the code
The verifyCommand method is in the directory /bin/utils/index.js.
To start writing this method, let’s install a few libraries: FS, FS-extra, and PATH.
const fs = require("fs");
const { readdirSync } = require("fs-extra");
const { join } = require("path");
module.exports = {
// Check whether the command is' add 'or' page '.
verifyCommand: (command, type) = > {
if (command === "add") {
if (["page"."pages"."p"].indexOf(type) ! = = -1) {
return "page"; }}return "";
},
// Read the names of all files and folders in the/SRC /components folder
getComponents: (path = ".. /.. /src/components") = > {
return readdirSync(join(__dirname, path)).filter((pkg) = > {
return pkg.charAt(0)! = =".";
});
},
// Check whether the pageName entered by the user is in our project
checkNameExist: (list = [], name) = > {
if(list.indexOf(name) ! = = -1) {
return true;
}
return false; }};Copy the code
After writing these methods, remember to import these methods in the /bin/index.js file:
const { verifyCommand, checkNameExist, getComponents } = require("./utils");
Copy the code
Okay so now let’s test that out.
File recursive migration
We are going to copy the page to the/SRC /pages/blockTemplate folder of the test project.
Before implementing the feature, let’s consider the logic of this:
- We need to make a judgment call before migrating the code
/src/pages/blockTemplate
Whether the component already exists in the directory. If one already exists, the operation is terminated with a prompt. - Try copying the first layer of files under this folder first.
- Implement the above steps and then think about how to recursively copy files.
/bin/index.js
const createBlockFile = require("./createBlockFile");
/** * command line parsing */
const commanderAction = (command, type, name) = > {
if (verifyCommand(command, type) === "page") {
if (checkNameExist(getComponents(), name)) {
createBlockFile(type, name);
} else{}...// Omit some code here
};
Copy the code
Create a new createBlockfile.js file in the /bin directory to handle the recursive copy of the file.
To determine whether the component exists, implement createBlockfile.js or continue to implement it in utils/index.js:
module.exports = {
checkBlockExist: (name) = > {
let dirName = process.cwd(); // Returns the current working directory of the Node.js process
const filePath = join(dirName, "src/pages"."blockTemplate");
if (fs.existsSync(filePath)) {
if (fs.existsSync(join(filePath, name))) {
return false;
}
return true;
} else {
return true; }}};Copy the code
/bin/createBlockFile.js
const color = require("colors-cli");
const { copy } = require("fs-extra");
const { join } = require("path");
const { checkBlockExist, getComponents } = require("./utils");
module.exports = function createBlockFile(type, name) {
const flag = checkBlockExist(name);
const copyFolder = (path) = > {
let dName = process.cwd();
const currentPath = `.. /.. /src/components/${path}`; // Get the path to the component
const fileList = getComponents(currentPath); // Get the file name under the file
fileList.forEach((item) = > {
// Check whether it is a file or folder
// There are better ways to do this
if (item.indexOf(".")! = = -1) {
const targetPath = join(__dirname, `.. /src/components/${path}`, item); // The file path under the component library
const createPath = join(
dName,
"src/pages"."blockTemplate",
path,
item
); // Path to the demo file
console.log(color.green("write:"), createPath);
copy(targetPath, createPath);
} else {
// Migrate code recursively
copyFolder(`${path}/${item}`); }}); };if (flag) {
copyFolder(name);
console.log("\n", color.green(Block created successfully!!), "\n");
} else {
console.log(
color.blue("/src/blockTemplate "),
color.red('path is already contained${name}Folder, please redefine the page name! `)); }};Copy the code
It is easiest to write the whole set of code directly, some of the code has been added to the annotations, small partners can understand the line by line.
I won’t say much, but I’ll go directly to the screenshot to see the effect.
The code address