The cause of
In my work, I encountered the need to create a new management side permission control project (based on Vue family bucket) in multiple markets. At present, the open source VUE scaffolding is generally used in VUE-CLI, but in the actual use process I have written many common and reusable common components on the original project. If vuE-CLI is used, CTRL + C and CTRL + V operations are unavoidable, which is very tedious. So I came up with the idea of building a front-end scaffolding for this type of project. Yeoman-genarator was selected to build the scaffolding project after some research, which was successfully implemented and reused in multiple markets. One is to learn new things, the second is really quite convenient, new project cool. So this is not a tutorial, just a way to successfully complete the Generator myself. Please kindly advise ([email protected]). The scaffolding has been uploaded to NPM (Generator-manage-CLI) and you are welcome to download it. [git link] : (github.com/wuhaoxiangf…).
Understand the Yeoman
Why yeoman
Yeoman was developed by the Google team in collaboration with a team of outside contributors, His goal was to create an easy-to-use workflow for developers wrapped around Grunt, a command-line tool for development task automation, and Bower, a package manager for front-end resources such as HTML, CSS, Javascript, and images.
Yeoman’s aim is not only to establish a workflow for new projects, but also to solve many of the serious problems faced by front-end development, such as fragmented dependencies.
Yeoman consists of three main parts: Yo (scaffolding tool), Grunt (Build tool), and Bower (package manager). These three tools were developed independently, but need to work together to achieve our efficient workflow pattern.
This is the introduction of the official website. Since I am used to webpack (build tool) and NPM (package management tool), I used these two auxiliary tools to build the scaffolding in this project.
Simple use of Yeoman
NPM is required to install yo Generator-generator
npm install -g yo
npm install -g generator-generator
Copy the code
We then run generator-Generator to create our own generator infrastructure
yo generator
Copy the code
After a series of setup problems, note that the scaffold name must begin with generator
? Your generator name generator-manegewhx
Your generator must be inside a folder named generator-manegewhx
I'll automatically create this folder.
? Description a demo for yeoman generator
? Project homepage url
? Author's Name whx
? Author's Email [email protected]
? Author's Homepage
? Package keywords (comma to split) generator
? Send coverage reports to coveralls No
? GitHub username or organization wuhaoxiangfau
? Which license do you want to use? (Use arrow keys)
? Which license do you want to use?
? Which license do you want to use? MIT
Copy the code
We get the directory for generator:
├ ─ ─ generators / │ └ ─ ─ app / │ ├ ─ ─ index. The js │ └ ─ ─ templates / │ └ ─ ─ dummyfile. TXT ├ ─ ─ the editorconfig ├ ─ ─ the gitattributes ├ ─ ─ . Gitignore ├ ─ ─. Eslintrc ├ ─ ─. Travis. Yml ├ ─ ─. Yukio okamoto, - rc. Json ├ ─ ─ package. The json ├ ─ ─ gulpfile. Js ├ ─ ─ the README. Md ├ ─ ─ LICENSECopy the code
Taking action
To prepare the template
The first thing I did was prepare some templates files that I was going to build the base project, put them in the templates folder, and delete the default dummyfile.txt. This is Yeoman’s default folder for template files, although you can also use templatePath to set up other folders. I don’t want to complicate things here. Please refer to the API documentation on the official website for details.
Since it’s a demo file, I’m going to put some simple template files in and not complicate them, allowing for a little slack.
└ ─ templates ├ ─ the build configuration file is / / webpack ├ ─ config / / webpack configuration file ├ ─ SRC / / resource file │ ├ ─ components / / component │ │ ├ ─ based components, basic / / │ │ └ ─ frame │ ├─ ├─ exercises, ├─ exercises, ├─ exercises, ├─ exercises, ├─ exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises └ ─ the resource / / vue - resource └ ─ the staticCopy the code
Write index. Js
How our generator generates what kind of infrastructure, directory structure, whether it automatically installs dependencies, and so on are all done in this step. Key code will be posted and explained.
Prompting block
prompting() {
const prompts = [
{
type: 'input'.name: 'projectName'.message: 'Please input project name (manage_app):'.default: 'manage_app'
},
{
type: 'input'.name: 'description'.message: 'Please input project description:'
},
{
type: 'input'.name: 'projectMain'.message: 'Main file (main.js):'.default: 'main.js'
},
{
type: 'input'.name: 'projectAuthor'.message: 'Author :',},];return this.prompt(prompts).then(props= > {
this.props = props;
});
}
Copy the code
We need to collect user build project data by means of questions. Promts is a set of problems that are raised when this.promt is called to run yo, and then the user input is saved in this.props for later calls.
Defaults block
defaults() {
if (path.basename(this.destinationPath()) ! = =this.props.projectName) {
mkdirp(this.props.projectName);
this.destinationRoot(this.destinationPath(this.props.projectName)); }}Copy the code
Mkdirp is the module we refer to to create folders. This.destinationroot is the root directory to set up the project to be created.
Writing blocks
writing() {
/ / create the readme
let readmeTpl = _.template(this.fs.read(this.templatePath('README.md')));
this.fs.write(this.destinationPath('README.md'), readmeTpl({
generatorName: 'generator-managecli'.yoName: 'managecli'
}));
/ / create packageJson
let pkg = this.fs.readJSON(this.templatePath('package_tmpl.json'), {}); extend(pkg,{dependencies: {"babel-polyfill": "^ 6.26.0"."element-ui": "^ 2.2.1." "."font-awesome": "^ 4.7.0"."vue": "^ 2.5.2." "."vue-resource": "^ 1.5.0." "."vue-router": "^ 3.0.1." "."vuex": "^ 3.0.1." "
},
devDependencies: {"autoprefixer": "^ 7.1.2." "."babel-core": "^ 6.22.1"."babel-helper-vue-jsx-merge-props": "^ 2.0.3"."babel-loader": "^ 7.1.1." "."babel-plugin-syntax-jsx": "^ 6.18.0"."babel-plugin-transform-runtime": "^ 6.22.0"."babel-plugin-transform-vue-jsx": "^ 3.5.0." "."babel-preset-env": "^ 1.3.2." "."babel-preset-stage-2": "^ 6.22.0"."chalk": "^ 2.0.1." "."copy-webpack-plugin": "^ 4.0.1." "."css-loader": "^ 0.28.0"."extract-text-webpack-plugin": "^ 3.0.0"."file-loader": "^ 1.1.4." "."friendly-errors-webpack-plugin": "^ 1.6.1." "."html-webpack-plugin": "^ 2.30.1"."node-notifier": "^ 5.1.2." "."optimize-css-assets-webpack-plugin": "^ 3.2.0"."ora": "^ 1.2.0"."portfinder": "^ 1.0.13"."postcss-import": "^ 11.0.0"."postcss-loader": "^ mid-atlantic moved." "."postcss-url": "^ 7.2.1"."rimraf": ^ "server"."semver": "^ 5.3.0." "."shelljs": "^ 0.7.6"."uglifyjs-webpack-plugin": "^ 1.1.1"."url-loader": "^ 0.5.8"."vue-loader": "^ 13.3.0"."vue-style-loader": "^ 3.0.1." "."vue-template-compiler": "^ 2.5.2." "."webpack": "^ 3.6.0"."webpack-bundle-analyzer": "^ 2.9.0"."webpack-dev-server": "^ 2.9.1." "."webpack-merge": "^ 4.1.0." "}}); pkg.keywords = pkg.keywords || []; pkg.keywords.push('generator-manage-cli');
pkg.name = this.props.projectName;
pkg.description = this.props.description;
pkg.main = this.props.projectMain;
pkg.author = this.props.projectAuthor;
pkg.license = 'MIT';
this.fs.writeJSON(this.destinationPath('package.json'), pkg);
// Create a folder
mkdirp('build');
mkdirp('config');
mkdirp('static');
mkdirp('src/assets');
mkdirp('src/router');
mkdirp('src/store');
mkdirp('src/tool');
mkdirp('src/tool/pubService');
mkdirp('src/tool/resource');
mkdirp('src/components');
mkdirp('src/components/basic');
mkdirp('src/components/frame');
this.fs.copy(
this.templatePath('gitignore_tmpl'),
this.destinationPath('.gitignore'));this.fs.copy(
this.templatePath('babelrc_tmpl'),
this.destinationPath('.babelrc'));this.fs.copy(
this.templatePath('index_tmpl.html'),
this.destinationPath('index.html'));this.fs.copy(
this.templatePath('editorconfig_tmpl'),
this.destinationPath('.editorconfig'));this.fs.copy(
this.templatePath('.postcssrc_tmpl.js'),
this.destinationPath('.postcssrc.js'));/ / SRC directory
this.fs.copy(
this.templatePath('src/main_tmpl.js'),
'src/main.js'
);
this.fs.copy(
this.templatePath('src/App.vue'),
'src/App.vue'
);
// SRC components/frame directory
this.fs.copy(
this.templatePath('src/components/frame/myPage.vue'),
'src/components/frame/myPage.vue'
);
this.fs.copy(
this.templatePath('src/components/frame/mySearch.vue'),
'src/components/frame/mySearch.vue'
);
this.fs.copy(
this.templatePath('src/components/frame/myTreeList.vue'),
'src/components/frame/myTreeList.vue'
);
// SRC components/basic
this.fs.copy(
this.templatePath('src/components/basic/myAsideMenu.vue'),
'src/components/basic/myAsideMenu.vue'
);
this.fs.copy(
this.templatePath('src/components/basic/myDropDown.vue'),
'src/components/basic/myDropDown.vue'
);
// SRC components load the file
this.fs.copy(
this.templatePath('src/components/index.js'),
'src/components/index.js'
);
// SRC pages/basic directory basic business page
this.fs.copy(
this.templatePath('src/pages/basic/home.vue'),
'src/pages/basic/home.vue'
);
this.fs.copy(
this.templatePath('src/pages/basic/login.vue'),
'src/pages/basic/login.vue'
);
/ / SRC tool/pubService
this.fs.copy(
this.templatePath('src/tool/pubService/index.js'),
'src/tool/pubService/index.js'
);
/ / SRC tool/resource
this.fs.copy(
this.templatePath('src/tool/resource/api.js'),
'src/tool/resource/api.js'
);
this.fs.copy(
this.templatePath('src/tool/resource/client.js'),
'src/tool/resource/client.js'
);
this.fs.copy(
this.templatePath('src/tool/resource/interceptors.js'),
'src/tool/resource/interceptors.js'
);
// SRC tool directory
this.fs.copy(
this.templatePath('src/tool/Base64.js'),
'src/tool/Base64.js'
);
this.fs.copy(
this.templatePath('src/tool/myValidate.js'),
'src/tool/myValidate.js'
);
this.fs.copy(
this.templatePath('src/tool/smallTool.js'),
'src/tool/smallTool.js'
);
this.fs.copy(
this.templatePath('src/tool/Base64.js'),
'src/tool/Base64.js'
);
// SRC indicates the router directory
this.fs.copy(
this.templatePath('src/router/index.js'),
'src/router/index.js'
);
// SRC global state machine of store directory
this.fs.copy(
this.templatePath('src/store/index.js'),
'src/store/index.js'
);
this.fs.copy(
this.templatePath('src/store/menu.js'),
'src/store/menu.js'
);
this.fs.copy(
this.templatePath('src/store/user.js'),
'src/store/user.js'
);
/ / config directory
this.fs.copy(
this.templatePath('static/config.js'),
'static/config.js'
);
/ / build directory
this.fs.copy(
this.templatePath('build/build.js'),
'build/build.js'
);
this.fs.copy(
this.templatePath('build/check-versions.js'),
'build/check-versions.js'
);
this.fs.copy(
this.templatePath('build/utils.js'),
'build/utils.js'
);
this.fs.copy(
this.templatePath('build/vue-loader.conf.js'),
'build/vue-loader.conf.js'
);
this.fs.copy(
this.templatePath('build/webpack.base.conf.js'),
'build/webpack.base.conf.js'
);
this.fs.copy(
this.templatePath('build/webpack.dev.conf.js'),
'build/webpack.dev.conf.js'
);
this.fs.copy(
this.templatePath('build/vue-loader.conf.js'),
'build/vue-loader.conf.js'
);
this.fs.copy(
this.templatePath('build/webpack.prod.conf.js'),
'build/webpack.prod.conf.js'
);
/ / config directory
this.fs.copy(
this.templatePath('config/dev.env.js'),
'config/dev.env.js'
);
this.fs.copy(
this.templatePath('config/index.js'),
'config/index.js'
);
this.fs.copy(
this.templatePath('config/prod.env.js'),
'config/prod.env.js'
);
/ / static directory
this.fs.copy(
this.templatePath('static/config.js'),
'static/config.js'
);
}
Copy the code
Use _. Template (loDash’s template feature) and this.fs.write to replace keywords in the template with user input.
This.fs. readJSON and this.fs.writeJSON read the data from the package.json template and make some changes to write new files.
Finally, use mkdirp and this.fs.copy to build the project directory structure and copy some unmodified configuration files to the specified directory.
NPM release
If it is the first time to publish, you need to register with NPM adduser account. After registration, you must activate your email account otherwise it will fail to publish. I have encountered a pit here, so I will focus on it. If an NPM account exists, run the NPM login command to login. Then go to the project root directory and run NPM Publish to publish.
Because NPM’s repo download is slow, we often use Taobao’s repo. So you need to cut back to the NPM’s REPO when you publish.
I wish success!